《Linux操作系统分析》由会员分享,可在线阅读,更多相关《Linux操作系统分析(38页珍藏版)》请在金锄头文库上搜索。
1、Linux操作系统分析操作系统分析主讲:陈香兰助教:贾永泉、毛熠璐3606864-83(西区电三421)Autumn 2007xlanchen2007.10.25Linux中的信号中的信号xlanchen2007.10.25信号信号l信号在最早的Unix系统中就已经被引入了,用于在用户态进程间通信。l内核也用信号通知进程系统所发生的事情信号信号l信号是很短的消息l标准信号l标准信号没有给参数、消息或是其他相随的信息留有空间l通常使用一个数字来标识一个信号l信号可以被发送到一个进程或一组进程。软件中断的概念软件中断的概念l信号的产生和处理方式跟中断有些相似 l信号是典型的异步事件(当然也有一些事
2、件是同步错误或异常) l大多数产生信号的事件对进程而言是随机出现 l进程不可能做轮询来测试某个标志位或者变量来判别是否发生了一个信号,而是必须告诉内核“在某个信号发生时,应该执行如下操作”,这点跟中断处理例程相似,所以也不难理解标准信号不带参数或者是其他的信息 l跟硬件中断一样,任何动作,包括终止进程,都只能由接收到信号的进程来执行,也就是在本进程的上下文中执行 信号的作用信号的作用l使用信号的两个主要目的是:l让进程知道已经发生了一个特定的事件l强迫进程执行它自己代码中的信号处理程序l很多应用程序提供自己的信号处理程序l系统也会定义一些缺省的信号处理程序信号的生成信号的生成l异常l当一个进程
3、出现异常(比如试图执行一个非法指令,除0,浮点溢出等),内核通过向进程发送一个信号来通知进程异常的发生 l其他进程 l一个进程可以通过kill或是sigsend系统调用向另一个进程或一个进出组发送信号。一个进程也可以向自身发送信号l终端 l某些键盘字符如ctrl+c等会向终端的前台进程发送信号 l作业控制 l发送信号给那些想要读或写终端的后台进程。比如shell使用信号来管理前台和后台进程l配额限制 l当一个进程使用超过分配给它的cpu时间或是文件大小的限制,内核发送一个信号给这个进程 l通知 l一个进程也许要求能被通知某些事件的发生。比如设备已经就绪等待I/O操作l闹钟 l定时器产生的信号,
4、由内核发送给进程Linux/i386中的部分信号中的部分信号信号举例:信号举例: “Ctrl+c”组合键组合键l假设用户在console下按下ctrl+c,这将产生终端中断ltty驱动程序能识别出这个组合键,并向自己的前台进程发送一个SIGINT信号。l当对应进程被调度执行时,它将在上下文切换返回到用户态时检查到这个信号。l此外,通常前台进程就是被ctrl+c中断的current进程。当进程从中断返回时,也会检查到这个信号。l检查到信号后,系统就会让进程执行相应的动作。信号举例:异常信号举例:异常l前面讲过,异常也是通过信号来实现的。l当程序发生除0错误或是有非法指令时,将引起一个内核态的tr
5、ap。l内核trap处理程序识别出这个异常并发送合适的信号到当前进程。l当trap处理程序将要返回到用户态时,会检查并发现信号,进程可能就会被终止。异常处理程序异常处理程序发出的信号与信号相关的系统调用与信号相关的系统调用信号传递的两个不同阶段信号传递的两个不同阶段l信号产生l内核更新进程描述符中跟信号相关的数据结构来表示一个信号被发送给了这个进程l信号传递l内核强迫目标进程通过以下方式对信号作出反映:l或改变目标进程的执行状态,l或开始执行一个特定的信号处理程序,l或者两者都是挂起信号挂起信号l已经产生但还没有传递的信号称为挂起信号。l任何时候,一个进程仅存在给定类型的一个挂起信号,同一进程
6、同种类型的其他信号不被排队,只被简单的丢弃。l信号的挂起时间长度往往不可预知,原因在于:l信号通常只被current进程传递l进程可以选择阻塞某种信号。这种情况下,在取消阻塞之前进程将不接收这个信号l当进程执行一个信号处理程序函数时,通常屏蔽相应的信号,即自动阻塞这个信号直到处理程序结束。因此,所处理的信号的另一次出现不能中断信号处理程序信号的应答方式和响应时机信号的应答方式和响应时机l进程以三种方式对一个信号做出应答 1,显式的忽略这个信号l多数信号都可以使用这种方式进行处理。2,执行系统默认的缺省操作,可以是:lTerminate:进程被杀死lDump:进程被杀死,且如果可能,创建包含进程
7、上下文的可用于调试的core文件lIgnore:简单的忽略信号lStop:进程被停止,状态置为TASK_STOPPEDlContinue:如果进程被挂起,则状态置为TASK_RUNNING。否则忽略该信号l3,捕获信号l为了执行用户希望的对某个事件的处理,可以由用户指定某个信号的处理函数。信号的应答方式和响应时机信号的应答方式和响应时机l注意1:阻塞忽略l阻塞仅仅推迟了传递的时间l忽略的信号总是被传递,但是没有进一步的操作l注意2:有两种信号不可以被显式的忽略、捕获或阻塞:SIGKILL和SIGSTOP。因为它们向超级用户提供一种终止或停止进程的可靠的方法信号的应答方式和响应时机信号的应答方式
8、和响应时机l内核在如下时机检查进程的信号1 ,从系统调用/中断返回到用户态之前,在ret_from_intr中执行这个检查l这个检查几乎在每个定时中断时都发生(约10ms)l代码在i386kernelentry.S中 2,进程从一个可中断的事件醒来后 中断返回系统调用返回如果有信号要处理Entry.S中部分相关的代码中部分相关的代码内核在处理信号时需要注意的地内核在处理信号时需要注意的地方方l记住每个进程阻塞哪些信号l当从内核态切换到用户态时,要检查是否有信号到达进程l确定是否可以忽略信号。这发生在下列条件都满足时l目标进程没有被另一个进程跟踪l信号没有被阻塞l信号被目标进程忽略l处理这样的信
9、号,即信号可能在进程运行期间的任一时刻请求把进程切换到一个信号处理函数,并在这个函数返回以后恢复原来进程的执行与信号相关的数据结构与信号相关的数据结构l在进程描述符中与信号处理相关的字段有:记录进程想阻塞的信号22组32位信号,第一组sig0为32个标准信号记录被挂起的信号指出挂起的信号是什么被挂起的信号的相关信息组成的队列信号处理描述符指出共享signal_struct结构的进程个数每个信号的处理方法64如果有信号被挂起,就设置这个标志,前面的entry.S就根据这个快速判断有无挂起信号,并根据这个标志调用do_signall在i386体系结构上action数组中的每一个信号的描述符包含下列
10、域:lsa_handler或sa_sigactionl这是一个联合,表示如何处理这个信号,可能的值包括:1,SIG_DFL,即0,表示执行缺省操作2,SIG_IGN,即1,表示忽略这个信号3,指向一个信号处理程序的指针,表示按照用户指定的程序处理lsa_flags:一个标志集,指明与信号处理相关的一些其他信息lsa_mask:指定处理本信号时,应当屏蔽的信号发送信号发送信号l内核通过调用send_sig_info()send_sig(),force_sig()force_sig_info()这几个函数发送信号。这些函数只是更新目标进程的进程描述符相关的域。但在条件满足的情况下它们可以唤醒进程让
11、目标进程接收信号接收信号接收信号l内核在返回到用户态时调用do_signal()来处理非阻塞的挂起信号:参数:struct pt_regs *regs;/pt_regs结构,指向当前进 /程内核态堆栈中保存的寄存器sigset_t *oldset; /信号处理程序执行时要屏蔽的 /信号,实际上调用时为空ldo_signal()一位一位的检查当前被挂起的非阻塞信号,对应于上面介绍的action结构中指定的处理方法:l如果是SIG_IGN(忽略信号)不能被忽略的信号l如果是SIG_DFL(缺省操作)根据信号的类型,使用switch语句找到对应的缺省处理方式l如果信号有一个专门的处理程序,do_si
12、gnal就调用handle_signal()强迫执行该处理程序Handle_signall信号处理程序是用户态进程所定义的函数,并且包含在用户态的代码段中lHandle_signal运行在内核态,而信号处理程序运行在用户态l问题:1,必须返回用户态执行信号处理程序2,必须按照原来进入内核的方式返回用户态3,一旦返回用户态,内核堆栈就被清空,如何保存内核堆栈的内容lLinux采用的解决办法:l把保存在内核态堆栈中的上下文拷贝到当前进程的用户态堆栈中l建立好信号处理程序所需的堆栈环境l当信号处理程序运行结束时,调用sigreturn()系统调用把上面保存的内核堆栈的内容再拷贝回内核堆栈l然后正常返
13、回与信号处理相关的系统调用与信号处理相关的系统调用lkill(pid, sig)系统调用l发送信号,对应于sys_kill()l对于pid的值1,如果大于0,发送信号给指定的进程2,如果=0,把信号发送给同组的所有进程3,如果=-1,把信号发送给除0号、1号以及current进程之外的所有进程4,如果小于-1,把信号发送给指定的进程组中的所有的进程lsigaction(sig, act, oact)系统调用l允许用户为信号指定一个操作,对应于sys_sigaction()l参数:sig,指明是哪一个信号act,指定新的操作oact,可选,用来存放旧的操作lsignal(sig, handler)系统调用l设置信号处理程序为handler,对应于sys_singal()用户设置信号处理程序举例:用户设置信号处理程序举例: