Linux下,一个进程给其他进程发送信号的API是kill函数
#include
#include
int kill(pid_t pid, int sig);
//该函数把信号sig发送给目标进程
pid参数的含义如下:
pid参数 | 含义 |
---|---|
pid > 0 | 信号发送给PID为pid的进程 |
pid = 0 | 信号发送给本进程组内的其他进程 |
pid = -1 | 信号发送给除init进程外的所有进程,但发送者需要拥有对目标进程发送信号的权限 |
pid < -1 | 信号发送给组ID为-pid的进程组中的所有成员 |
该函数成功时返回0,失败返回-1并设置error。
在目标进程收到信号时,需要调用一个接收函数来处理,这个接收函数的原型如下:
#include
typedef void (*__sighandler_t) (int);
用户除了能用以上自定义函数以外,还能使用系统自带的函数进行处理
#include
#define SIG_IGN ((__sighandler_t) 1)
#define SIG_DFL ((__sighandler_t) 0)
SIG_IGN表示忽略目标信号,SIG_DFL表示使用信号的默认处理方式
下面函数可以为一个信号设置处理函数:
#include
_sighandler_t signal(int sig, _sighandler_t _handler)
其参数含义如下:
参数 | 含义 |
---|---|
sig | 表示要捕获的信号类型 |
_headler | 用于指定信号sig的处理函数,是_sighandler_t类型的函数指针 |
成功的话返回一个_sighandler_t类型的函数指针,它是前一次调用signal函数时传入的函数指针。如果是第一次调用signal的话,则返回的是sig对应的默认处理函数指针SIG_DEF。
出错的话返回SIG_ERR并设置error。
设置更健壮的信号处理函数则如下:
#include
int sigaction(int sig, const struct sigaction* act, struct sigaction* oact);
struct sigaction{
#define __USE_POSIX199309
union{
_sighadler_t sa_handler;
void (*sa_sigaction) (int , siginfo_t*, void*);
}
_sigaction_handler;
#define sa_handler __sigaction_handler.sa_headler
#define sa_sigaction __sigaction_handler.sa_sigaction
#else
_sighandler_t sa_handler;
#endif
_sigset_t sa_mask;
int sa_flags;
void (*sa_restorer) (void);
};
函数中的参数 | 含义 |
---|---|
sig | 表示要捕获的数据类型 |
act | 指定新的信号处理方式 |
oact | 输出信号先前的处理方式 |
结构体中的参数 | 含义 |
---|---|
sa_hander | 指定信号处理函数 |
sa_mask | 在进程原有信号掩码的基础上增加信号掩码 |
sa_flags | 设置程序收到信号时的行为 |
sigaction成功时返回0,失败时返回-1并设置error。
Linux使用数据结构sigset_t来表示一组信号,其定义如下:
#include
#define _SIGSET_NWORDS (1024 / (8 * sizeof(unisigned long int )))
typedef struct{
unisigned long int __val[_SIGSET_NWORDS];
}__sigset_t;
由此可见,sigset_t是一个长整型的数组,其中每个元素的每个位表示一个信号,这种定义方式与fd_set类似。
并且,Linux提供了以下函数来对其进行操作。
#include
int sigemptyset(sigset_t* _set); //清空信号集
int sigfillset(sigset_t* _set); //在信号集中设置所有信号
int sigaddset(sigset_t* _set, int _signo);//将信号_signo添加到信号集中
int sigdelset(sigset_t* _set, int _signo);//将信号_signo从信号集中删除
int sigismember(_const sigset_t* _set, int _signo);//测试_signo是否在信号集中
这里可以使用sigprocmask来设置或查看进程掩码:
#include
int sigprocmask(int _how, _const sigset_t* _set, sigset_t* _oset);
参数 | 含义 |
---|---|
_set | 新的信号掩码 |
_oset | 原来的信号掩码(如果不为NULL的话) |
_how | 设置进程信号掩码的方式 |
如果_set为NULL的话,则信号掩码不变,此时仍然可以用_oset来获得进程当前的信号掩码。
sigprocmask成功时返回0,失败返回-1并设置error。
在设置信号掩码后,被屏蔽的信号将无法被进程接收,该信号会被设置为一个挂起的信号,如果我们使用以下函数对其取消挂起,则它能立即被该进程接收到:
#include
int sigpending(sigset_t* set);
set参数用于保存被挂起的信号集。
该函数成功时返回0,失败时返回-1并设置error。
《Linux高性能服务器编程》学习笔记