分类:
2008-03-19 09:37:18
信号产生的时候不会立刻出现在进程中,它们必须等到进程下次运行。每一次进程从系统调用中退出的时候都要检查它的 signal 和 blocked 域,如果有任何没有阻塞的信号,就可以发送。这看起来好像非常不可靠,但是系统中的每一个进程都在调用系统调用,比如向终端写一个字符的过程中。如果愿意,进程可以选择等待信号,它们挂起在 Interruptible 状态,直到有了一个信号。 Linux 信号处理代码检查 sigaction 结构中每一个当前未阻塞的信号。
如果信号处理程序设置为缺省动作,则核心会处理它。 SIGSTOP 信号的缺省处理是把当前进程的状态改为 Stopped ,然后运行调度程序,选择一个新的进程来运行。 SIGFPE 信号的缺省动作是让当前进程产生 core ( core dump ),让它退出。变通地,进程可以指定自己的信号处理程序。这是一个例程,当信号产生的时候调用而且 sigaction 结构包括这个例程的地址。 Linux 必须调用进程的信号处理例程,至于具体如何发生是和处理器相关。但是,所有的 CPU 必须处理的是当前进程正运行在核心态,并正准备返回到调用核心或系统例程的用户态的进程。解决这个问题的方法是处理该进程的堆栈和寄存器。进程程序计数器设为它的信号处理程序的地址,例程的参数加到调用结构或者通过寄存器传递。当进程恢复运行的时候显得信号处理程序是正常的调用。
Linux 是 POSIX 兼容的,所以进程可以指定调用特定的信号处理程序的时候要阻塞的信号。这意味着在调用进程的信号处理程序的时候改变 blocked 掩码。信号处理程序结束的时候, blocked 掩码必须恢复到它的初始值。因此, Linux 在收到信号的进程的堆栈中增加了对于一个整理例程的调用,把 blocked 掩码恢复到初始值。 Linux 也优化了这种情况:如果同时几个信号处理例程需要调用的时候,就在它们堆积在一起,每次退出一个处理例程的时候就调用下一个,直到最后才调用整理例程。
5.管道是单向的字节流,把一个进程的标准输出和另一个进程的标准输入连接在一起。没有一个进程意识到这种重定向,和它平常一样工作。是 shell 建立了进程之间的临时管道。在 Linux 中,使用指向同一个临时 VFS I 节点(本身指向内存中的一个物理页)的两个 file 数据结构来实现管道。图 5.1 显示了每一个 file 数据结构包含了不同的文件操作例程的向量表的指针:一个用于写,另一个从管道中读。这掩盖了和通用的读写普通文件的系统调用的不同。当写进程向管道中写的时候,字节拷贝到了共享的数据页,当从管道中读的时候,字节从共享页中拷贝出来。 Linux 必须同步对于管道的访问。必须保证管道的写和读步调一致,它使用锁、等待队列和信号( locks , wait queues and signals )。