分类: LINUX
2012-01-23 21:01:34
++++++APUE读书笔记-10信号-09kill和raise函数++++++
9、kill和raise函数
================================================
kill用来给一个进程或者一组进程发送信号,raise函数允许进程给它自己发送信号。
raise原来是由ISO C定义的.POSIX.1把它包含进来,并且让它自己(指的谁?)符合ISO C的标准,但是POSIX.1扩展了raise让它可以支持多线程情况(后面我们会讨论多线程下面如何进行信号的交互)。因为ISO C不能处理多进程,所以它不能定义像kill这样需要一个进程ID参数这样的函数。
#include
int kill(pid_t pid, int signo);
int raise(int signo);
两个函数在成功的时候返回0,在错误的时候返回1(kill一般是-1,raise是非0)。
调用raise(signo);等价于kill(getpid(),signo);
对于kill的参数,有以下四种不同的情况:
a)pid > 0 表示信号发送给进程ID值为pid的进程。
b)pid == 0 表示信号发送给所有进程组ID和发送者进程组ID一样的,并且当前发送进程有相应权限发送的所有的进程。注意,这里提到的“ 所有的进程”指的是排除了基于系统实现定义的系统进程。对于大多数UNIX系统,这样的系统进程几何包括内核进程init(它的pid为1).
c)pid < 0 信号发送给所有进程组id等于pid的绝对值的,并且当前发送进程有相应权限发送的所有的进程。这里提到的“ 所有的进程”也排除了基于系统实现定义的系统进程。
pid == 1 信号发送给系统中sender有相应权限发送的所有的进程。同样,这里提到的“ 所有的进程”也排除了基于系统实现定义的系统进程。
如前所述,一个进程发送信号给另外一个进程,需要一定的权限。超级用户可以发送信号给任何进程,对于其他用户,一个基本得原则就是,发送进程的real或者effective用户ID 与接收进程的real或者effective用户ID一样;如果实现支持_POSIX_SAVED_IDS(现在POSIX.1要求这样),那么就会把检测effective用户ID的部分替换成检测saved set-user-ID的部分。当然,对于权限检测这里也有例外的情况:如果被发送的信号是SIGCONT,那么进程可以把它发送给任何与它在同一个会话中的其他进程。
POSIX.1把信号号0做为空信号。如果signo参数是0,那么kill只进程普通的错误检测,并不会发送信号。这个经常用来决定一个指定的进程是否存在。如果我们给进程发送一个空的信号,但是这个进程不存在,那么kill会返回1,然后把errno设置为ESRCH。然而,我们需要注意UNIX系统会在一定的时间之后回收进程ID,所以一个给定进程ID的存在的进程,并不一定就是你所想像的那个进程。
还需要知道的是,这个测试进程存在的方法不是原子的。当kill给调用这返回答案的时候,那个进程可能已经退出了,所以返回值是受限制的。
如果调用kill导致给调用者产生了信号,而且这个信号不是被阻塞的,(无论是信号号还是其他的提交),没有被阻塞的信号教会在kill返回之前发送给进程(在线程中会有其他的情况,后面会提到)。
参考: