linux信号类型:
linux中信号的处理一般分为四步
1、信号集的安装和登记
2、信号集操作
3、信号的发送
4、信号的接收
下面分阶段详细说明
1、信号集的安装和登记
使用sigaction函数对信号进行安装和登记
ngx_init_signals(ngx_log_t *log)
{
ngx_signal_t *sig;
struct sigaction sa;
for (sig = signals; sig->signo != 0; sig++) {
ngx_memzero(&sa, sizeof(struct sigaction));
sa.sa_handler = sig->handler; //注册信号的处理函数
sigemptyset(&sa.sa_mask); //将信号集初始化为空,暂时不阻塞该信号
if (sigaction(sig->signo, &sa, NULL) == -1) { //安装登记当前信号
return NGX_ERROR;
}
return NGX_OK;
}
其中:
sigaction函数:
函数原型:
int sigaction(int signum,const struct sigaction *act ,struct sigaction *oldact)
函数说明:
sigaction()会依参数signum指定的信号编号来设置该信号的处理函数
参数说明:
参数结构sigaction定义如下
struct sigaction
{
void (*sa_handler) (int);
void (*sa_sigaction)(int, siginfo_t *, void *);
sigset_t sa_mask;
int sa_flags;
void (*sa_restorer) (void);
}
① sa_handler:此参数和signal()的参数handler相同,此参数主要用来对信号旧的安装函数signal()处理形式的支持
② sa_sigaction:新的信号安装机制,处理函数被调用的时候,不但可以得到信号编号,而且可以获悉被调用的原 因以及产生问题的上下文的相关信息。
③ sa_mask:用来设置在处理该信号时暂时将sa_mask指定的信号搁置
④ sa_restorer: 此参数没有使用
⑤ sa_flags:用来设置信号处理的其他相关操作,下列的数值可用。可用OR 运算(|)组合
Ÿ A_NOCLDSTOP:如果参数signum为SIGCHLD,则当子进程暂停时并不会通知父进程
Ÿ SA_ONESHOT/SA_RESETHAND:当调用新的信号处理函数前,将此信号处理方式改为系统预设的方式
Ÿ SA_RESTART:被信号中断的系统调用会自行重启
Ÿ SA_NOMASK/SA_NODEFER:在处理此信号未结束前不理会此信号的再次到来
Ÿ SA_SIGINFO:信号处理函数是带有三个参数的sa_sigaction
2、信号集的操作
/*初始化信号集*/
sigemptyset(&set);
/*将下面的信号都加入信号集中*/
sigaddset(&set, SIGCHLD);
sigaddset(&set, SIGALRM);
sigaddset(&set, SIGIO);
sigaddset(&set, SIGINT);
sigaddset(&set, ngx_signal_value(NGX_RECONFIGURE_SIGNAL));
sigaddset(&set, ngx_signal_value(NGX_REOPEN_SIGNAL));
sigaddset(&set, ngx_signal_value(NGX_NOACCEPT_SIGNAL));
sigaddset(&set, ngx_signal_value(NGX_TERMINATE_SIGNAL));
sigaddset(&set, ngx_signal_value(NGX_SHUTDOWN_SIGNAL));
sigaddset(&set, ngx_signal_value(NGX_CHANGEBIN_SIGNAL));
/*设置信号集的阻塞字,即信号的处理方式*/
if (sigprocmask(SIG_BLOCK, &set, NULL) == -1) {
ngx_log_error(NGX_LOG_ALERT, cycle->log, ngx_errno,
"sigprocmask() failed");
}
/*暂时忽略这些信号的处理*/
sigemptyset(&set);
====================================================================
其中涉及的函数有三个:
sigemptyset:初始化信号集合为空。
sigaddset:将指定信号加入到信号集合中去。
sigprocmask:
每个进程都有一个用来描述哪些信号递送到进程时将被阻塞的信号集,该信号集中的所有信号在递送到进程后都将被阻塞。调用函数sigprocmask可设定信号集内的信号阻塞或不阻塞。其函数原型及说明如下:
int sigprocmask(int how,const sigset_t *set,sigset_t *oset)
参数说明:
how(决定函数的操作方式):
SIG_BLOCK:增加一个信号集合到当前进程的阻塞集合之中
SIG_UNBLOCK:从当前的阻塞集合之中删除一个信号集合
SIG_SETMASK:将当前的信号集合设置为信号阻塞集合
set:指定信号集
oset:信号屏蔽字
3、信号的发送
ngx_int_t ngx_os_signal_process(ngx_cycle_t *cycle, char *name, ngx_int_t pid)
{
ngx_signal_t *sig;
for (sig = signals; sig->signo != 0; sig++) {
if (ngx_strcmp(name, sig->name) == 0) {
if (kill(pid, sig->signo) != -1) {
return 0;
}
}
}
return 1;
}
调用kill函数来发送信号,对于kill函数的说明,参见以下文章:
用kill函数传递信号 int kill(pid_t pid,int sig)
4、信号的处理
使用sigsuspend阻塞进程等待信号处理,
int sigsuspend(const sigset_t *sigmask);
pause函数使调用进程挂起直到捕捉到一个信号。只有执行了一个信号处理程序并从其返回时,pause才返回
sigsuspend的整个原子操作过程为:
(1) 设置新的mask阻塞当前进程;
(2) 收到信号,调用该进程设置的信号处理函数;
(3) 待信号处理函数返回后,恢复原先mask;
(4) sigsuspend返回