kill和raise函数
kill函数发送信号到进程或进程组。raise函数允许一个进程发送信号到它自己。
raise曾定义于ISO C。POSIX.1包含了该函数并和ISO C标准对齐,但是POSIX.1扩展了raise的特性,具有了线程功能。因为ISO C并不支持多进程,它不能和kill这样的函数配合使用,因为它需要进程ID参数。
|
调用:
raise(signo);
等同于调用
kill(getpid(), signo);
kill函数的pid参数有4种不同的条件:
pid>0 信号发送到进程ID是pid的进程。
pid==0 信号发送到进程组ID等于调用kill函数的进程组ID的所有进程。并且该进程要有发送该信号的权限。注意:术语所有进程不包含实现定义的系统进程集。对于多数UNIX系统,这个系统进程集包含了内核进程和init(pid是1)。
pid<0 信号被发送到进程组ID为pid的绝对值的所有进程,要保证调用者有权限发送该信号。同样所有进程并不包含系统进程集。
pid==1 信号发送到系统上的所有的进程(只包含那些该进程有权限的进程)。同样不包含系统进程集。
就像我们之前提到的,一个进程需要权限才能发送信号到另一个进程。超级用户能发送信号到任意进程。对于其它用户,基本规则是:发送信号进程的实际或有效用户ID必须等于接收信号的实际或有效用户。如果实现支持_POSIX_SAVED_IDS(POSIX.1要求),检查接收者的SAVED SET-USER-ID代替它检查的有效用户ID。也有一个权限测试的特殊案例:如果开始发送SIGCONT信号,进程可以在同一会话中发送到任意其它进程。
POSIX.1定义了0号信号做为空信号。如果signo参数是0,那么kill执行一般错误检查,但是不发送任何信号。这通常用于确定一个特定的进程是否存在。如果我们向一个进程发送空信号并且该进程不存在,kill返回1并errno设置成ESRCH。要知道,UNIX系统每过一段时间都要回收进程ID,所以并不是给出的ID都是存在有效的。
同样要知道,这个测试进程是否存在并不是原子操作。可能在kill返回值的同时,该进程又存在了,所以这个答案也是有待商榷的。
如果调用某进程调用kill产生的信号,对于该进程来说,如果信号没有被阻塞,要么signo或其它正在准备,解除阻塞信号被交付到该进程要先于kill函数返回。