10.9 kill以及raise函数
kill函数用于发送信号给一个进程或者是一个进程组,函数raise允许进程发送一个信号给自身。
raise函数最开始定义与ISO C中,POSIX.1为了与兼容ISO C标准,于是包含了函数raise,但是POSIX.1将函数raise的特性扩展到了线程处理(我们将在12.8中讨论线程是如何与信号发生交互的),因为ISO C并不处理多进程,它并不能定义向kill这样的函数,因为kill函数需要使用一个进程ID的参数。
#include <signal.h>
int kill(pid_t pid, int signo);
int raise(int signo);
Both return: 0 if OK,-1 on error.
The call
raise(signo);
is equilent to the call:
kill(getpid(), signo);
对于kill的参数pid,有四种不同的条件:
pid条件 | 含义 |
---|---|
pid>0 | 信号被发送到进程ID为pid的进程 |
pid == 0 | 信号被发送到所有进程组ID与发送进程的进程组ID一致的进程,注意属于”所有进程”包含了实现定义的系统进程集合,对于许多UNIX系统,这个系统进程集合包含了内核进程以及init(pid 1). |
pid < 0 | 信号被发送到所有进程组ID等于pid绝对值且调用该函数的进程有权限发送信号的进程,同样的,所有进程的集合包含了某些系统进程,正如前面描述的那样 |
pid == -1 | 信号被发送到系统上所有调用该函数的进程有权限的所有进程,正如前文所述,该集合包含了某些系统进程。 |
超级用户可以发送信号到任意进程,对于其他的用户而言,基本规则是:发送进程的real or effective user id必须等于接收进程的real or effective user ID,如果实现支持_POSIX_SAVED_IDS(POSIX.1要求支持),那么就会检查接收进程的saved set-user-id而不是其effective user ID,对于上述权限检查的一个特例是:如果发送的信号是SIGCONT,那么任意处于相同会话的所有进程都可以接收它。
POSIX.1定义了信号编号0为null信号,如果signo参数传递的是0,然后正常的错误检查将被kill函数执行,但是并不会发送任何信号,该技术通常用于检查特定进程是否仍然存在,如果我们发给一个进程null信号,而接受进程已经不存在了,那么kill函数将会返回-1,同时errno将被设置为ESRCH,需要注意的是:UNIX系统会循环利用进程ID,所以一个相同进程ID的进程的出现并不一定意味着还是原来的进程.
如果kill函数的调用造成一个信号生成,并且发送的目标进程是调用进程自身,同时信号是不被阻塞的,那么未阻塞的信号就会在kill函数返回之前被发送到进程。