Linux 信号机制 (二)

来源:互联网 发布:centos mail 发送邮件 编辑:程序博客网 时间:2024/06/05 11:22

上一篇讲解了 Linux的 信号机制。
这一篇主要用于总结。

推荐一篇好文章 http://stonehorse.blog.51cto.com/2958823/1109790
文章二: http://www.ahlinux.com/start/base/20873.html

  1. 进程即将从内核态返回用户态的时候,才会处理信号(执行信号处理函数)
  2. 用户进程什么时候从内核态返回用户态呢?

    系统调用(用户主动进入内核)
    中断 (用户进程被动进入内核)
    被调度执行 (用户从等待执行,变为正在执行)

  3. 信号处理函数时用户态函数,但是需要在内核态的条件下执行。所以需要一定的trick.

  4. 内核处理一个进程收的信号的时机是在进程从内核态返回到用户态时。 所以一个进程在内核态运行的时候,软终端信号并不会立即起作用,需要等到用户态的时候才处理。 进程只有处理完 信号才会返回用户态,进程在用户态下不会有未处理的信号。

  5. 内核处理一个进程收到的软中断信号是在该进程的上下文中,因此,进程必须处于运行状态。如果进程收到一个要捕捉的信号,那么进程从内核态返回用户态时执行 用户定义的函数。而且执行用户定义的函数的方法很巧妙,内核是在用户栈上创建一个新的层,该层中将返回地址的值设置成用户定义的处理函数的地址,这样进程 从内核返回弹出栈顶时就返回到用户定义的函数处,从函数返回再弹出栈顶时,才返回原先进入内核的地方,接着原来的地方继续运行。这样做的原因是用户定义的 处理函数不能且不允许在内核态下执行(如果用户定义的函数在内核态下运行的话,用户就可以获得任何权限)。


在信号的处理方法中有几点特别要引起注意

第一,在一些系统中,当一个进程处理完中断信号返回用户态之前,内核清除用户区中设定的对该信号的处理例程的地
址,即下一次进程对该信号的处理方法又改为默认值,除非在下一次信号到来之前再次使用signal系统调用。这可能会使得进程在调用signal之前又得
到该信号而导致退出。在BSD中,内核不再清除该地址。但不清除该地址可能使得进程因为过多过快的得到某个信号而导致堆栈溢出。为了避免出现上述情况。在
BSD系统中,内核模拟了对硬件中断的处理方法,即在处理某个中断时,阻止接收新的该类中断

Linux下应该不会清除注册的函数地址,另外Linux下是允许 信号处理函数重入的。

第二个要引起注意的是,如果要捕捉的信号发生于进程正在一个系统调用中时,并且该进程睡眠在可中断的优先级上(若系统调用未睡眠而是在运行,根据上面的分
析,等该系统调用运行完毕后再处理信号),这时该信号引起进程作一次longjmp,跳出睡眠状态,返回用户态并执行信号处理例程。当从信号处理例程返回
时,进程就象从系统调用返回一样,但返回了一个错误如-1,并将errno设置为EINTR,指出该次系统调用曾经被中断。这要注意的是,BSD系统中内
核可以自动地重新开始系统调用,或者如上面所述手动设置重启。

这里的意思是: 进程因为系统调用处于可中断的睡眠状态下, 接受到了一个信号跳出了睡眠状态。 这本身是不合理的,因为在等待系统调用的完成。 所以需要自动重新开始系统调用。

第三个要注意的地方:若进程睡眠在可中断的优先级上,则当它收到一个要忽略的信号时,该进程被唤醒,但不做longjmp,一般是继续睡眠。但用户感觉不
到进程曾经被唤醒,而是象没有发生过该信号一样。所以能够使pause、sleep等函数从挂起态返回的信号必须要有信号处理函数,如果没有什么动作,可
以将处理函数设为空。

这里的意思是: 若进程睡眠在可中断的优先级上,但是收到的信号默认状态是忽略。该进程被唤醒,但是会继续睡眠,用户感觉不到进程曾经被唤醒。 (这里的意思是,会将该进程加入到可执行队列,但是信号的默认动作是忽略,进程还是会继续睡眠(如何继续睡眠呢? 重新调用系统调用吗?还是怎么样)。)

第四个要注意的地方:内核对子进程终止(SIGCLD)信号的处理方法与其他信号有所区别。当进程正常或异常终止时,内核都向其父进程发一个SIGCLD
信号,缺省情况下,父进程忽略该信号,就象没有收到该信号似的,如果父进程希望获得子进程终止的状态,则应该事先用signal函数为SIGCLD信号设
置信号处理程序,在信号处理程序中调用wait

SIGCLD信号的作用是唤醒一个睡眠在可被中断优先级上的进程。如果该进程捕捉了这个信号,就象普通信号处理一样转到处理例程。如果进程忽略该信号,则
什么也不做。其实wait不一定放在信号处理函数中,但这样的话因为不知道子进程何时终止,在子进程终止前,wait将使父进程挂起休眠。

wait 系统调用可以放在 中断处理函数中吗, 其原理是怎么样的呢?

0 0
原创粉丝点击