信号发送接口包括raise,kill,killpg,tkill,tgkill,pthread_kill,sigqueue等。
1. raise()
/**
* raise用于向进程自身发送信号
* 成功返回0,失败返回非0值,并置errno.
* 只有信号处理函数执行完毕之后,raise才能返回。
*
* 对于单线程的程序而言,相当于调用了如下语句:
* kill(getpid(), sig);
*
* 对于多线程的程序而言,相当于调用了如下语句:
* pthread_kill(pthread_self(), sig);
*/
#include <signal.h>
int raise(int sig);
2. kill()
/**
* kill函数用于发送信号,不仅可以向特定进程组发送信号,也可以向特定进程发送信号.
* 根据参数pid的不同,分为如下几种情况:
* pid > 0, 发送信号给进程ID等于pid的进程。
* pid = 0, 发送信号给调用进程所在的同一个进程组的每一个进程。
* pid = -1, 有权限向调用进程发送信号的所有进程发送信号,init进程和进程自身除外
* pid < -1, 向进程组-pid发送信号。
* sig = 0,检测目标进程或目标进程组是否存在,如果返回-1并且errno为ESRCH表示目标
* 或目标进程组不存在。
*
* 成功返回0,失败返回-1,并置errno
*
*/
#include <sys/types.h>
#include <signal.h>
int kill(pid_t pid, int sig);
3. killpg()
/**
* 向进程组发送信号
* pgrp = 0,向进程自身所在进程组发送信号。
* pgrp <= 1,将引发未定义的行为。
*
* 成功返回0,失败返回-1并置errno.
*
*/
#include <signal.h>
int killpg(int pgrp, int sig);
4. tkill() & tgkill()
/*
* 向线程发送信号
*
* 这两个都是内核提供的系统调用,glibc并没有提供对这两个系统调用的封装,如果使用
* 这两个函数,需要采用syscall的方式:
* ret = syscall(SYS_tkill, tid, sig);
* ret = syscall(SYS_tgkill, tgid, sig);
* 成功返回0,失败返回-1并置errno
*
* tkill是一个过时的接口,并不推荐使用它来向线程发送信号。相比之下,tgkill接口更加
* 安全。tgkill系统调用的第一个参数tgid,为线程中主线程的线程ID,或者称为进程号。
* 这个参数能够起到保护作用,防止向错误的线程发送信号。进程ID或线程ID是由内核负责
* 管理,进程或线程有自己的生命周期,使用tkill发送信号有可能线程已经退出,这时候会
* 将信号发送到不相关的进程上,为了防止出现这种情况,内核引入了tgkill系统调用,
* 含义是向线程组ID是tgid、线程ID为tid的线程发送信号,避免发错信号。
* 这两个函数是Linux特有的,存在一致性问题。
*
*/
int tkill(int tid, int sig);
int tgkill(int tgid, int tid, int sig);
5. pthread_kill()
/**
* 向同一个进程内的线程发送信号
*
* 成功返回0,失败返回错误码。
* 如果sig = 0,将不发送任何信号。
* 如果向一个已经退出的线程发送信号,将会引发未定义的行为。比如说段错误等。
* 编译的时候加上-pthread选项
*
*/
#include <signal.h>
int pthread_kill(pthread_t thread, int sig);
6. sigqueue()
/**
* 向进程ID等有pid的进程发送信号和数据
* 成功返回0,失败返回-1并置errno
*
* 第三个参数为伴随数据,可以向目标进程发送一个整形数据或者指针,当目标进程注册
* 信号处理函数使用了SA_SIGINFO标志位的时候就可以接收到该数据
*
* union sigval {
* int sival_int;
* void *sival_ptr;
* };
*
* 发送sig = 0的信号可以用来检测目标进程是否存在,返回错误码为ESRCH
*
*
*
*/
#include <signal.h>
int sigqueue(pid_t pid, int sig, const union sigval value);
参考资料:
1. 《Linux环境编程,从应用到内核》高峰,李彬著
2. man signal : http://www.man7.org/linux/man-pages/man7/signal.7.html