2003 年 01 月 【相关文章:Neighbour table over】
【扩展阅读:Linux一句话问答(2005-5-19】 linux信号机制远远比想象的复杂,本文力争用最短的篇幅,对该机制做了深入细致的分析。信号应用实例将在信号(下)中给出。 【扩展信息:Fedora Core3 下 MySQL】 一、信号及信号来源 信号本质 信号是在软件层次上对中断机制的一种模拟,在原理上,一个进程收到一个信号与处理器收到一个中断请求可以说是一样的。信号是异步的,一个进程不必通过任何操作来等待信号的到达,事实上,进程也不知道信号到底什么时候到达。 信号是进程间通信机制中唯一的异步通信机制,可以看作是异步通知,通知接收信号的进程有哪些事情发生了。信号机制经过posix实时扩展后,功能更加强大,除了基本通知功能外,还可以传递附加信息。 信号来源 信号事件的发生有两个来源:硬件来源(比如我们按下了键盘或者其它硬件故障);软件来源,最常用发送信号的系统函数是kill, raise, alarm与setitimer以及sigqueue函数,软件来源还包括一些非法运算等操作。 二、信号的种类 可以从两个不同的分类角度对信号进行分类:(1)可靠性方面:可靠信号与不可靠信号;(2)与时间的关系上:实时信号与非实时信号。在«linux环境进程间通信(一):管道及有名管道»的附1中列出了系统所支持的所有信号。 1、可靠信号与不可靠信号 "不可靠信号" linux信号机制基本上是从unix系统中继承过来的。早期unix系统中的信号机制比较简单与原始,后来在实践中暴露出一些问题,因此,把那些建立在 早期机制上的信号叫做"不可靠信号",信号值小于sigrtmin(red hat 7.2中,sigrtmin=32,sigrtmax=63)的信号都是不可靠信号。这就是"不可靠信号"的来源。它的主要问题是: • 进程每次处理信号后,就将对信号的响应设置为默认动作。在某些情况下,将导致对信号的错误处理;因此,用户如果不希望这样的操作,那么就要在信号处理函数结尾再一次调用signal(),重新安装该信号。 • 信号可能丢失,后面将对此详细阐述。 因此,早期unix下的不可靠信号主要指的是进程可能对信号做出错误的反应以及信号可能丢失。 linux支持不可靠信号,但是对不可靠信号机制做了改进:在调用完信号处理函数后,不必重新调用该信号的安装函数(信号安装函数是在可靠机制上的实现)。因此,linux下的不可靠信号问题主要指的是信号可能丢失。 "可靠信号" 随着时间的发展,实践证明了有必要对信号的原始机制加以改进与扩充。所以,后来出现的各种unix版本分别在这方面进行了研究,力图实现"可靠信 号"。由于原来定义的信号已有许多应用,不好再做改动,最终只好又新增加了一些信号,并在一开始就把它们定义为可靠信号,这些信号支持排队,不会丢失。同 时,信号的发送与安装也出现了新版本:信号发送函数sigqueue()及信号安装函数sigaction()。posix.4对可靠信号机制做了标准 化。但是,posix只对可靠信号机制应具有的功能以及信号机制的对外接口做了标准化,对信号机制的实现没有作具体的规定。 信号值位于sigrtmin与sigrtmax之间的信号都是可靠信号,可靠信号克服了信号可能丢失的问题。linux在支持新版本的信号安装 函数sigation()以及信号发送函数sigqueue()的同时,仍然支持早期的signal()信号安装函数,支持信号发送函数kill()。 注:不要有这样的误解:由sigqueue()发送、sigaction安装的信号就是可靠的。事实上,可靠信号是指后来添加的新信号(信号值 位于sigrtmin及sigrtmax之间);不可靠信号是信号值小于sigrtmin的信号。信号的可靠与不可靠只与信号值有关,与信号的发送及安装 函数无关。目前linux中的signal()是通过sigation()函数实现的,因此,即使通过signal()安装的信号,在信号处理函数的结尾 也不必再调用一次信号安装函数。同时,由signal()安装的实时信号支持排队,同样不会丢失。 对于目前linux的两个信号安装函数:signal()及sigaction()来说,它们都不能把sigrtmin以前的信号变成可靠信号 (都不支持排队,仍有可能丢失,仍然是不可靠信号),而且对sigrtmin以后的信号都支持排队。这两个函数的最大区别在于,经过sigaction安 装的信号都能传递信息给信号处理函数(对所有信号这一点都成立),而经过signal安装的信号却不能向信号处理函数传递信息。对于信号发送函数来说也是 一样的。 2、实时信号与非实时信号 早期unix系统只定义了32种信号,ret hat7.2支持64种信号,编号0-63(sigrtmin=31,sigrtmax=63),将来可能进一步增加,这需要得到内核的支持。前32种信 号已经有了预定义值,每个信号有了确定的用途及含义,并且每种信号都有各自的缺省动作。如按键盘的ctrl ^c时,会产生sigint信号,对该信号的默认反应就是进程终止。后32个信号表示实时信号,等同于前面阐述的可靠信号。这保证了发送的多个实时信号都 被接收。实时信号是posix标准的一部分,可用于应用进程。 非实时信号都不支持排队,都是不可靠信号;实时信号都支持排队,都是可靠信号。 三、进程对信号的响应 进程可以通过三种方式来响应一个信号:(1)忽略信号,即对信号不做任何处理,其中,有两个信号不能忽略:sigkill及sigstop; (2)捕捉信号。定义信号处理函数,当信号发生时,执行相应的处理函数;(3)执行缺省操作,linux对每种信号都规定了默认操作,详细情况请参考 [2]以及其它资料。注意,进程对实时信号的缺省反应是进程终止。 linux究竟采用上述三种方式的哪一个来响应信号,取决于传递给相应api函数的参数。 四、信号的发送 发送信号的主要函数有:kill()、raise()、 sigqueue()、alarm()、setitimer()以及abort()。 1、kill() #include #include int kill(pid_t pid,int signo) 参数pid的值 信号的接收进程 pid>0 进程id为pid的进程 pid=0 同一个进程组的进程 pid<0 pid!=-1 进程组id为 -pid的所有进程 pid=-1 除发送进程自身外,所有进程id大于1的进程 sinno是信号值,当为0时(即空信号),实际不发送任何信号,但照常进行错误检查,因此,可用于检查目标进程是否存在,以及当前进程是否具有 向目标发送信号的权限(root权限的进程可以向任何进程发送信号,非root权限的进程只能向属于同一个session或者同一个用户的进程发送信 号)。 kill()最常用于pid>0时的信号发送,调用成功返回 0; 否则,返回 -1。... 下一页