UINX 信号(上)

信号机制也是进程之间相互传递消息的一种方法,但作为进程间通信来介绍是不合适的。信号全称为软中断信号,也有人称作软中断。从它的命名可以看出,它的实 质和使用很象中断。所以,信号可以说是进程控制的一部分。这里将它单独作为一章,是因为它有独特和重要的作用。下面我们就来介绍信号。

1    信号的基本概念
        本节先介绍信号的一些基本概念,然后给出一些基本的信号类型和信号对应的事件。基本概念对于理解和使用信号,对于理解信号机制都特别重要。下面就来看看什么是信号。

1.1    基本概念
        软中断信号(signal,又简称为信号)用来通知进程发生了异步事件。进程之间可以互相通过系统调用kill发送软中断信号。核心也可以因为内部事件而 给进程发送信号,通知进程发生了某个事件。注意,信号只是用来通知某进程发生了什么事件,并不给该进程传递任何数据。

        收到信号的进程对各种信号有不同的处理方法。处理方法可以分为三类:第一种是类似中断的处理程序,对于需要处理的信号,进程可以指定处理函数,由该函数来 处理。第二种方法是, 忽略某个信号,对该信号不做任何处理,就象未发生过一样。第三种方法是,对该信号的处理保留系统的默认值,这种缺省操作,对大部分的信号的缺省操作是使得 进程终止。进程通过系统调用signal来指定进程对某个信号的处理行为。
        在进程表的表项中有一个软中断信号域,该域中每一位对应一个信号,当有信号发送给进程时,对应位置位。由此可以看出,进程对不同的信号可以同时保留,但对于同一个信号,进程并不知道在处理之前来过多少个。

1.2    信号的类型
    发出信号的原因很多,这里按发出信号的原因简单分类,以了解各种信号:
    (1) 与进程终止相关的信号。当进程退出,或者子进程终止时,发出这类信号。
    (2) 与进程例外事件相关的信号。如进程越界,或企图写一个只读的内存区域(如程序正文区),或执行一个特权指令及其他各种硬件错误。
    (3) 与在系统调用期间遇到不可恢复条件相关的信号。如执行系统调用exec时,原有资源已经释放,而目前系统资源又已经耗尽。
    (4) 与执行系统调用时遇到非预测错误条件相关的信号。如执行一个并不存在的系统调用。
    (5) 在用户态下的进程发出的信号。如进程调用系统调用kill向其他进程发送信号。
    (6) 与终端交互相关的信号。如用户关闭一个终端,或按下break键等情况。
    (7) 跟踪进程执行的信号。

常见的信号名称及含义

信号名                           默认处理动作                  发出信号的原因                             符合标准

              

SIGHUP                1            终止程序                            终端挂起                                          POSIX

SIGINT                2            终止程序                            中断键(如break)被按下                 ANSI

SIGQUIT              3            核心映像转储coredump       键盘的退出键被按下                        POSIX

SIGILL                 4            core dump                           遇到非法指令                                   ANSI

SIGTRAP             5             core dump                          跟踪捕捉                                          POSIX

SIGIOT                6            core dump                           I/O捕捉指令,硬件故障                   4.2 BSD

SIGABRT             6             core dump                          核心标准子例程abort发出                 ANSI

SIGEMT         7,-,7             core dump                           仿真捕捉指令                                   4.2 BSD

SIGFPE                8            core dump                           浮点异常                                          ANSI

SIGKILL             9             终止程序                            终止程序                                          POSIX

SIGBUS        10,7,10           core dump                           总线错误                                          4.2 BSD

SIGSEGV            11            core dump                           段违例                                              ANSI

SIGSYS         12,-,12           core dump                            调用不存在的系统调用                      SVID

SIGPIPE               13           终止程序                            写一个没有读端口的管道                  POSIX

SIGALRM             14           终止程序                            实时定时器计时到                            POSIX

SIGTERM             15           终止程序                            软件结束信号                                   ANSI

SIGURG       16,23,21         忽略该信号                         Socket出现紧急条件                         4.2 BSD

SIGSTOP       17,19,23         停止进程                            停止进程(不能被捕捉或忽略)            POSIX

SIGTSTP       18,20,24         停止进程                            从键盘产生的进程停止信号              POSIX

SIGCONT      19,18,25         忽略该信号                         进程继续(曾被停止的进程)           POSIX

SIGCHLD      20,17,18         忽略该信号                         子进程状态改变                                OSIX

SIGCLD         -,-,18             忽略该信号                         同上(只是定义名字不同)              SYSV

SIGTTIN       21,21,26         停止进程                            后台进程企图从控制终端读              POSIX

SIGTTOU      22,22,27         停止进程                            后台进程企图向控制终端写              POSIX

SIGIO            23,29,22         忽略该信号                         某I/O操作现在可以进行了               4.2 BSD

SIGXCPU      24,24,30         终止程序                            超出设定的CPU时间限制                  4.2 BSD

SIGXFSZ       25,25,31         终止程序                            超出设定的文件大小限制                4.2 BSD

SIGVTALRM26,26,28         终止程序                            实际时间报警时钟信号                     4.2 BSD

SIGPROF       27,27,29         终止程序                            Profile定时器到时                            4.2 BSD

SIGWINCH    28,28,20         忽略该信号                         窗口大小改变                                 4.3 BSD

SIGINFO         29,-,-            忽略该信号                         键盘请求状态信息                           4.2 BSD

SIGUSR1       30,10,16         终止程序                            用户自定义信号1                             POSIX

SIGUSR2       31,12,17         终止程序                            用户自定义信号2                             POSIX

SIGSTKFLT   -,16,-             终止程序                            协处理器堆栈错误                           SYSV

SIGPWR       29,30,19         终止程序                            电源故障,系统重启                       SYSV

         在UNIX系统V的版本2中有19个信号,目前还有所增加。上面介绍的35个信号是常见系统所支持的。我们以表格的形式介绍了各种信号的名称、作用及其在 默认情况下的处理动作。表4-1中各种默认处理动作的含义是:终止程序是指进程退出;忽略该信号是将该信号丢弃,不做处理;停止程序是指程序挂起,进入停 止状况以后还能重新进行下去,一般是在调试的过程中(ptrace系统调用);核心映像转储是指将进程数据在内存的映像和进程在核心结构中存储的部分内容 以一定格式转储到文件系统,并且进程退出执行,这样做的好处是为程序员提供了方便,使得他们可以得到进程当时执行时的数据值,允许他们确定转储的原因,并 且可以调试他们的程序。

        注意  信 号SIGKILL和SIGSTOP既不能被捕捉,也不能被忽略。信号SIGIOT与SIGABRT是一个信号。对于表中的信号值一列是标出信号的取值,表 中给出了三个取值(只给出一个信号值时,表示三个取值相同),第一个取值一般对应于alpha和sparc平台,中间的对应于i386和PowerPC, 最后一个对应于mips。当然在不同系统中的实现可能不同,这取决于读者使用的系统的实现。所以建议最好使用为信号定义的名字,而不要直接使用信号的值。

2      信 号 机 制

          上一节中介绍了信号的基本概念,在这一节中,我们将介绍核心如何实现信号机制。即核心如何向一个进程发送信号、进程如何接收一个信号、进程怎样控制自己对 信号的反应、核心在什么时机处理和怎样处理进程收到的信号。还要介绍一下setjmp和longjmp在信号中起到的作用。

2.1     核心对信号的基本处理方法

         核心给一个进程发送软中断信号的方法,是在进程所在的进程表项的信号域设置对应于该信号的位,这个概念在第一节中已经提到。这里要补充的是,如果信号发送 给一个正在睡眠的进程,那么要看该进程进入睡眠的优先级,如果进程睡眠在可被中断的优先级上,则唤醒进程;否则仅设置进程表中信号域相应的位,而不唤醒进 程。这一点比较重要,因为进程检查是否收到信号的时机是:一个进程在即将从核心态返回到用户态时;或者,在一个进程要进入或离开一个适当的低调度优先级睡 眠状态时。
         核心处理一个进程收到的信号的时机是在一个进程从核心态返回用户态时。所以,当一个进程在核心态下运行时,软中断信号并不立即起作用,要等到将返回用户态时才处理。进程只有处理完信号才会返回用户态,进程在用户态下不会有未处理完的信号。
         核心处理一个进程收到的软中断信号是在该进程的上下文中,因此,进程必须处于运行状态。前面介绍概念的时候讲过,处理信号有三种类型:进程接收到信号后退 出;进程忽略该信号;进程收到信号后执行用户设定用系统调用signal的函数。这些在表4-1中有详细的描述。当进程接收到一个它忽略的信号时,进程丢 弃该信号,就象没有收到该信号似的继续运行。如果进程收到一个要捕捉的信号,那么进程从核心态返回用户态时执行用户定义的函数。而且执行用户定义的函数的 方法很巧妙,核心是在用户栈上创建一个新的层,该层中将返回地址的值设置成用户定义的处理函数的地址,这样进程从核心返回弹出栈顶时就返回到用户定义的函 数处,从函数返回再弹出栈顶时,才返回原先进入核心的地方。这样做的原因是用户定义的处理函数不能且不允许在核心态下执行(如果用户定义的函数在核心态下 运行的话,用户就可以获得任何权限)。
         在信号的处理方法中有几点特别要引起注意。第一,在一些系统中,当一个进程处理完中断信号返回用户态之前,核心清除u区中设定的对该信号的处理例程的地 址,即下一次进程对该信号的处理方法又改为默认值,除非在下一次信号到来之前再次使用signal系统调用。这可能会使得进程在调用signal之前又得 到该信号而导致退出。在BSD中,核心不再清除该地址。但不清除该地址可能使得进程因为过多过快的得到某个信号而导致堆栈溢出。为了避免出现上述情况。在 BSD系统中,核心模拟了对硬件中断的处理方法,即在处理某个中断时,阻止接收新的该类中断。
         第二个要引起注意的是,如果要捕捉的信号发生于进程正在一个系统调用中时,并且该进程睡眠在可中断的优先级上,这时该信号引起进程作一次longjmp, 跳出睡眠状态,返回用户态并执行信号处理例程。当从信号处理例程返回时,进程就象从系统调用返回一样,但返回了一个错误代码,指出该次系统调用曾经被中 断。这要注意的是,BSD系统中核心可以自动地重新开始系统调用。
         第三个要注意的地方:若进程睡眠在可中断的优先级上,则当它收到一个要忽略的信号时,该进程被唤醒,但不做longjmp,一般是继续睡眠。但用户感觉不到进程曾经被唤醒,而是象没有发生过该信号一样。
         第四个要注意的地方:核心对子进程终止(SIGCLD)信号的处理方法与其他信号有所区别。当进程检查出收到了一个子进程终止的信号时,缺省情况下,该进 程就象没有收到该信号似的,如果父进程执行了系统调用wait,进程将从系统调用wait中醒来并返回wait调用,执行一系列wait调用的后续操作 (找出僵死的子进程,释放子进程的进程表项),然后从wait中返回。SIGCLD信号的作用是唤醒一个睡眠在可被中断优先级上的进程。如果该进程捕捉了 这个信号,就象普通信号处理一样转到处理例程。如果进程忽略该信号,那么系统调用wait的动作就有所不同,因为SIGCLD的作用仅仅是唤醒一个睡眠在 可被中断优先级上的进程,那么执行wait调用的父进程被唤醒继续执行wait调用的后续操作,然后等待其他的子进程。
         如果一个进程调用signal系统调用,并设置了SIGCLD的处理方法,并且该进程有子进程处于僵死状态,则核心将向该进程发一个SIGCLD信号。

2.2    setjmp和longjmp的作用

        前面在介绍信号处理机制时,多次提到了setjmp和longjmp,但没有仔细说明它们的作用和实现方法。这里就此作一个简单的介绍。
        在介绍信号的时候,我们看到多个地方要求进程在检查收到信号后,从原来的系统调用中直接返回,而不是等到该调用完成。这种进程突然改变其上下文的情况,就 是使用setjmp和longjmp的结果。setjmp将保存的上下文存入u区,并继续在旧的上下文中执行。这就是说,进程执行一个系统调用,当因为资 源或其他原因要去睡眠时,核心为进程作了一次setjmp,如果在睡眠中被信号唤醒,进程不能再进入睡眠时,核心为进程调用longjmp,该操作是核心 为进程将原先setjmp调用保存在进程u区的上下文恢复成现在的上下文,这样就使得进程可以恢复等待资源前的状态,而且核心为setjmp返回1,使得 进程知道该次系统调用失败。这就是它们的作用。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值