kill函数将信号发送给进程或进程组。raise函数则允许进程向自身发送信号。
#include <signal.h> int kill(pid_t pid, int signo); int raise(int signo); 两个函数返回值:若成功则返回0,若出错则返回-1
调用
raise(signo);
等价于调用
kill(getpid(), signo);
kill的pid参数有4种不同的情况:
pid > 0 将该信号发送给进程ID为pid的进程。
pid == 0 将该信号发送给与发送进程属于同一进程组的所有进程(这些进程的进程组ID等于发送进程的进程组ID),而且发送进程具有向这些进程发送信号的权限。注意,这里用的术语“所有进程”不包括实现定义的系统进程集。对于大多数UNIX系统,系统进程集包括内核进程以及init(pid 1)。
pid < 0 将信号发送给其进程组ID等于pid的绝对值的进程组中的所有进程,而且发送进程具有向其发送信号的权限。如上所述,“所有进程”不包括某些系统进程。
pid == –1 将该信号发送给发送进程有权限向它们发送信号的系统上的所有进程。如上所述,“所有进程”不包括某些系统进程。
进程将信号发送给其他进程需要权限:
超级用户可将信号发送给任一进程。
对于非超级用户,其基本规则是发送者的实际或有效用户ID必须等于接收者的实际或有效用户ID。如果实现支持_POSIX_SAVED_IDS,则检查接收者的保存的设置用户ID(而不是其有效用户ID)。在对权限进行测试时也有一个特例:如果被发送的信号是SIGCONT,则进程可将它发送给属于同一会话的任何其他进程。
POSIX.1将编号为0的信号定义为空信号。如果signo参数是0,则kill仍执行正常的错误检查,但不发送信号。这常被用来确定一个特定进程是否仍旧存在。如果向一个并不存在的进程发送空信号,则kill返回-1,并将errno设置为ESRCH。但是,应当了解,UNIX系统在经过一段时间后会重新使用进程ID,所以一个现有的具有所给定进程ID的进程并不一定就是你想要的进程。
还应该理解的是,对于进程是否存在的这种测试不是原子操作。在kill向调用者返回测试结果时,原来存在的被测试进程此时可能已经终止,所以这种测试并无多大价值。
如果调用kill为调用进程产生信号,而且此信号是不被阻塞的,那么在kill返回之前,就会将signo或者某个其他未决的非阻塞信号传送至该进程。(对于线程而言,还有一些附加条件)。
本篇博文内容摘自《UNIX环境高级编程》(第二版),仅作个人学习记录所用。关于本书可参考:http://www.apuebook.com/。