为用户编程:终端控制和.ppt

上传人:xt****7 文档编号:5159391 上传时间:2020-01-22 格式:PPT 页数:74 大小:648.31KB
返回 下载 相关 举报
为用户编程:终端控制和.ppt_第1页
第1页 / 共74页
为用户编程:终端控制和.ppt_第2页
第2页 / 共74页
为用户编程:终端控制和.ppt_第3页
第3页 / 共74页
点击查看更多>>
资源描述
第七讲为用户编程 终端控制和信号 主要内容 软件工具与用户程序读取和修改终端驱动程序的设置非阻塞输入用户输入的超时信号fcntl及signal系统调用 与终端有关的程序 用户常用的程序例如vi emacs及许多游戏程序经常要有终端进行交互它们设置终端驱动程序的击键和输出处理方式用户经常用到的几种用户终端设置 立即响应击键事件有限的输入集输入的超时屏蔽Ctrl C 终端驱动程序的模式 rotate c include includeintmain intc while c getchar EOF if c z c a elseif islower c c putchar c 规范模式 缓冲和编辑 使用默认设置运行该程序 退格键 gccrotate c orotate rotateabx cdbcdeefg C 输入的内容及程序所得到的内容 rotate程序 终端驱动程序 显示器及键盘 标准输入处理的特征 程序未得到输入的x 因为删除了它击键的同时字符显示在屏幕上 但直到按了回车 程序才接收到输入 C键结束输入并终止程序程序rotate并不负责这些事情 对于输入的缓冲 回显 编辑和控制键处理都由驱动程序完成标准输入处理的这些特征被启动时 将终端连接称为规范模式 非规范处理 stty icanon rotateabbcxy cddeeffggh sttyicanonstty icanon命令关闭驱动程序中的规范模式处理非规范模式没有缓冲 输入字母 a 驱动程序跳过缓冲层 字符直接送到程序 然后程序显示字符 b 用户输入未缓冲可能会带来麻烦 如果用户想修改输入时 此时将无法修改 终端模式小结 规范模式 是用户常见的模式输入的字符保存在缓冲区接收到回车键时才将其中内容发送到程序缓冲功能使驱动程序可实现编辑功能 例如删除字符 单词或者行可通过命令stty或者系统调用tcsetattr修改执行上述操作的特定键 终端模式小结 非规范模式 缓冲和编辑功能被关闭时 连接被称为处于非规范模式设备驱动器仍然进行特定字符的处理 例如Ctrl C及换行符及回车符之间的转换删除单词 字符及终止编辑键将不具有特殊含义而是被视作常规的数据输入 终端模式小结 raw模式 每个处理步骤都被一个独立的位控制 例如ISIG位控制Ctrl C是否用于终止一个程序程序可随意关闭所有这些处理步骤当所有处理都被关闭后 驱动程序将输入直接传递给程序 这种模式就称为raw模式sttyraw命令 编写一个用户程序 play again c play again c的逻辑 对用户显示提示问题接受输入如果是y返回0如果是n返回1第一个play again0 c程序 play again0 c的不足 必须先按回车 程序才能接受到数据当用户按回车键时 程序接收整行的数据对其进行处理 例如Doyouwantanothertransaction y n surething surething 改进方法 首先关闭规范输入 使得程序能够在用户敲键的同时得到输入的字符set crmode structtermiosttystate tcgetattr 0 installsettings tty mode inthow staticstructtermiosoriginal mode if how 0 tcgetattr 0 程序的主要过程 首先调用tty mode 0 函数保存当前终端的设置信息set crmode 函数首先将终端置于一个字符接一个字符的模式然后调用函数显示一个提示符 并获得一个响应最后调用tty mode 1 函数还原终端的设置 将终端置入字符输入模式包括两部分工作 将ICANON位关闭将控制字符数组中的VMIN下标元素置一 VMIN的值告诉驱动程序一次可以读取多少个字符 编译执行play again1程序 此时 程序可以直接接收和处理字符而不用等待回车键但对每个非法字符都提示错误信息 可能比较烦可关闭回显模式 丢掉不需要的字符 直到得到可接收的字符为止在set crmode函数中加入语句ttystate c lflag ECHO 阻塞与非阻塞输入 当调用getchar或者read等函数从文件描述符读数据时 这些调用一直等待用户的输入 如果用户不输入 则继续等待 这种行为就术语阻塞输入阻塞不仅仅是终端连接的属性 而且是任何一个打开文件的属性可使用fcntl或者open 通过开启O NDELAY标志为文件描述符启动非阻塞输入 非阻塞读取文件 关闭文件描述符的阻塞状态 然后从中read时 结果如何呢 如果能够获得输入 read返回输入数据及字符个数 如果没有输入字符 read返回0 就像遇到文件末尾一样 有错误 返回 1 每个文件都有一块保存未读取数据的地方 若文件描述符置了O NDELAY并且该空间为空 则read返回0 play again3 c get response intinput printf s y n question ask fflush stdout forceoutput while 1 sleep SLEEPTIME waitabit input tolower get ok char getnextchr if input y return0 if input n return1 if maxtries 0 outatime return2 sayso BEEP 实验结果 在输入后 程序会延时一会儿如果长时间不输入 程序也会退出 fflush out 函数 终端驱动对于输出也是一行行缓冲的直到它收到一个换行符或者程序试图从终端读取数据时才会进行输出而此时getchar被延迟读入 因此通过该函数将提示信息输出到屏幕上 否则用户将看不到提示信息 Ctrl C 执行上述程序时 如果输入Ctrl C则程序终止运行 同时 也终止了整个登录会话原因是什么呢 Ctrl C 设置O NDELAY设置crmode显示提示符等待用户输入用户输入恢复tty设置恢复fcntl标志退出 程序流程 CtrlC 进程被终止 进程正常退出时流向 Ctrl C 程序接收到Ctrl C后 会立即退出 此时 无法执行重置启动程序的代码返回shell并从用户获得命令行时 终端仍处于非阻塞模式 shell调用read获取命令行 但是因为处于非阻塞状态 read立即返回0 这时shell程序就退出原因总结 程序结束时 文件描述符处于一个错误的状态 信号 Ctrl C中断当前运行的程 这个中断由内核的信号机制产生Ctrl C的过程 用户输入Ctrl C驱动程序收到字符匹配VINTR和ISIG的字符被开启驱动程序调用信号系统信号系统发送SIGINT到进程进程收到SIGINT进程消亡 什么是信号 信号是由单个词组成的消息 例如红绿灯所发出的信息Ctrl C时 内核向当前运行的进程发送中断信号每个信号都有一个数字编码 中断信号编码通常是2 信号的来源 信号来自内核生成信号的请求来自3个地方 用户 通过输入Ctrl C Ctrl 等请求内核产生信号内核 进程执行出错时 内核向进程发送一个信号 例如非法段访问 浮点数溢出等 也可通知进程特定事件的发生 进程 通过系统调用kill给另一个进程发送信号 进程之间可通过信号通信 同步与异步信号 由进程的某个操作产生的信号称为同步信号 例如被零除用户击键这样的进程外的事件引起的信号称为异步信号 信号列表 信号编号及其名字可在 usr include signal h文件中找到 例如SIGINT为中断信号 SIGQUIT退出信号 SIGSEGV非法段访问信号可以使用信号消灭一个进程 也有办法保护自己不被杀死 进程处理信号的方法 进程通过signal系统调用告诉内核如何处理信号进程有3个选择 1 接受默认处理SIGINT默认处理为消亡 进程通过系统调用signal SIGINT SIG DFL 恢复默认处理 2 忽略信号signal SIGINT SIG IGN 系统调用告诉内核忽略该信号 进程处理信号的方法 3 调用一个函数 这是3种方法中最强大的一个 例如在play again3程序中 当用户输入Ctrl C时 程序收到信号后执行一个恢复设置的函数就不会发生上述情况了程序能够告诉内核 当信号来时调用哪个函数 signal SIGINT function 信号到来时所调用的函数称为信号处理函数 signal系统调用 signal系统调用 其中action可以是函数名也可以是如下两种特殊值之一 SIG IGN 忽略信号SIG DFL将信号恢复为默认处理signal返回前一个处理函数 值为指向该函数的指针 信号处理的例子sigdemo1 c include includemain voidf int declarethehandler inti signal SIGINT f installthehandler for i 0 i 5 i dosomethingelse printf hello n sleep 1 voidf intsignum thisfunctioniscalled printf OUCH n 信号处理过程 main signal SIGINT f for i 0 i 5 i printf hello n sleep 1 正常控制流 信号 函数f printf OUCH sigdemo1 c执行结果 hellohellohellohello COUCH hello 忽略信号sigdemo2 c include includemain signal SIGINT SIG IGN printf youcan tstopme n while 1 sleep 1 printf haha n sigdemo2 c程序执行结果 youcan tstopme hahahaha Chahahaha Chahahaha 退出 sigdemo2 c调用signal忽略中断信号 可以随意按Ctrl C而不会对程序产生影响 signal SIGINT SIG IGNT 作业 6 10 处理多个信号 当有多个信号到达进程时 该如何处理 1 捕鼠器问题 信号处理函数有点像捕鼠器早期版本中 在每次捕获之后 都必须重设它们 例如voidhandler ints signal SIGINT handler 1 捕鼠器问题 即使设置的速度非常快 它还是需要时间触发处理函数及重新设置完成之前 有新的信号或者老鼠溜走这一脆弱的间隙使得原有的信号处理不可靠 因此称为不可靠的信号 处理多个信号 第二个信号打断第一个信号的处理第二个信号被阻塞返回信号处理的地方是否要重新开始 信号的优先级 进程的多个信号 处理函数每次使用之后都要禁用吗 如果SIGY消息在进程处理SIGX消息时到达会发生什么 如果进程还在处理前一个SIGX时 第二个SIGX又到来会发生什么事情呢 第三个呢 如果信号到来时 程序正在处理getchar或者read之类的输入而阻塞 那会如何呢 测试多个信号sigdemo3 c程序 signal SIGINT inthandler sethandler signal SIGQUIT quithandler sethandler do printf nTypeamessage n nchars read 0 input INPUTLEN 1 if nchars 1 perror readreturnedanerror else input nchars 0 printf Youtyped s input while strncmp input quit 4 0 voidinthandler ints printf Receivedsignal d waiting n s sleep 2 printf Leavinginthandler n voidquithandler ints printf Receivedsignal d waiting n s sleep 3 printf Leavingquithandler n 执行结果 Typeamessagehelloyoutyped helloTypeamessage CReceivedsignal3 Receivedsignal2 LeavinginthandlerLeavingquithandler 各种实验 1 输入 C C C C 2 C C 3 hello CReturn 4 helloReturn C 5 hello C 第一种情况 不可靠的信号若两个SIGINT信号杀死了进程 则系统是不可靠的信号若未杀死进程 则处理函数在被调用后还有作用现代信号处理机制允许在两者之间选择默认情况下 为后者第一次实验的结果为 信号函数执行了两次 后面的两次函数丢失 第二种情况 SIGY打断SIGX的处理函数 接连按下 C和 时程序先跳到inthandler 然后跳到quithandler 然后再回到inthandler 最后回到主循环第二种情况的实验 接收到 后 程序进入quithandler程序 接收到 C后 进入inthandler程序 最后返回到quithandler程序说明信号 C打断信号 第三种情况 SIGX打断SIGX的处理函数 有三种可能 递归 调用同一个处理函数忽略第二个信号阻塞第二个信号直到第一个处理完毕第三种方法最好 系统调用被中断 例如当调用read或者getchar函数时 程序接收到 C的信号然后程序执行信号处理函数 执行完后 程序重新返回主循环程序是重新执行read还是从read返回同时设置errno为EINTR呢 实验结果 hello CReturn时 程序无法接收到hello输入helloReturn C时 程序可接收到hellohel CloReturn时 程序只接收到lo hello C时 无法得到hello输入 同时信号处理执行完后 重新开始read 信号机制其他的弱点 无法确定信号产生的原因 早期的模型只是告诉了信号的类型处理函数中无法安全阻塞其他消息voidinthandler ints intrv void prev qhandler prev qhandler signal SIGQUIT SIG IGN signal SIGQUIT prev qhandler 无法同时调用inthandler以及忽略SIGQUIT无法阻塞SIGQUIT信号 sigaction可以处理多个信号 定制信号处理structsigaction structsigaction void sa handler void sa sigaction int siginfo t void sigset tsa mask intsa flags 其中sa handler可以为SIG DFL SIG IGN或者函数名称 它是老的信号处理方式 sa sigaction为新的信号处理机制它可获得信号编号及被调用的原因及产生问题的上下文的相关信息使用旧的处理机制 structsigactionaction action sa handler handler old 使用新的处理机制 structsigactionaction action sa sigaction handler new 将sigaction中的标志位sa flags置为 SA SIGINFO sa flags标志
展开阅读全文
相关资源
相关搜索

当前位置:首页 > 图纸专区 > 课件教案


copyright@ 2023-2025  zhuangpeitu.com 装配图网版权所有   联系电话:18123376007

备案号:ICP2024067431-1 川公网安备51140202000466号


本站为文档C2C交易模式,即用户上传的文档直接被用户下载,本站只是中间服务平台,本站所有文档下载所得的收益归上传人(含作者)所有。装配图网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对上载内容本身不做任何修改或编辑。若文档所含内容侵犯了您的版权或隐私,请立即通知装配图网,我们立即给予删除!