一 点睛
sigaction:查询或设置信号处理方式
头文件
#include<signal.h>
定义函数
int sigaction(int signum,const struct sigaction *act ,struct sigaction *oldact);
函数说明
sigaction()会依参数signum指定的信号编号来设置该信号的处理函数。参数signum可以指定SIGKILL和SIGSTOP以外的所有信号。
结构sigaction定义如下
struct sigaction
{
void (*sa_handler) (int);
sigset_t sa_mask;
int sa_flags;
void (*sa_restorer) (void);
}
sa_handler:是一个函数指针,指向一个信号处理函数。
sa_mask:用来指定信号处理函数执行期间需要被屏蔽的信号,特别是当某个信号被处理时,它自身会自动放入进程的信号掩码,因此在信号处理函数执行期间,这个信号不会再度发生。
sa_restorer:此参数没有使用。
sa_flags:用来设置信号处理的其他相关操作,下列的数值可用。OR 运算(|)组合。
SA_NOCLDSTOP : 使父进程在它的子进程暂停或继续运行时不会收到SIGCHLD信号。
SA_RESTART:被信号中断的系统调用会自行重启
SA_NODEFER:在运行信号的处理函数时再次收到当前的信号,也会触发新处理函数调用。
返回值
执行成功则返回0,如果有错误则返回-1。
错误代码
EINVAL:参数signum 不合法, 或是企图拦截SIGKILL/SIGSTOPSIGKILL信号
EFAULT:参数act,oldact指针地址无法存取。
EINTR:此调用被中断
二 实战一——系统调用sigaction函数的简单使用
1 代码
#include <stdio.h>
#include <unistd.h>
#include <signal.h>
#include <errno.h>
static void sig_usr(int signum)
{
if (signum == SIGUSR1)
{
printf("SIGUSR1 received\n");
}
else if (signum == SIGUSR2)
{
printf("SIGUSR2 received\n");
}
else
{
printf("signal %d received\n", signum);
}
}
int main(void)
{
char buf[512];
int n;
struct sigaction sa_usr;
sa_usr.sa_flags = 0;
sa_usr.sa_handler = sig_usr; //信号处理函数
sigaction(SIGUSR1, &sa_usr, NULL);
sigaction(SIGUSR2, &sa_usr, NULL);
printf("My PID is %d\n", getpid());
while (1)
{
if ((n = read(STDIN_FILENO, buf, 511)) == -1)
{
if (errno == EINTR)
{
printf("read is interrupted by signal\n");
}
}
else
{
buf[n] = '\0';
printf("%d bytes read: %s\n", n, buf);
}
}
return 0;
}
2 第一个终端运行
[root@localhost test]# g++ -o test test.cpp
[root@localhost test]# ./test
My PID is 1939
3 第二个终端运行
[root@localhost ~]# kill -USR1 1939
4 第一个终端结果
SIGUSR1 received
read is interrupted by signal
三 实战二——sa_flags的简单使用
1 代码
#include <stdio.h>
#include <unistd.h>
#include <signal.h>
#include <errno.h>
static void sig_usr(int signum)
{
if (signum == SIGUSR1)
{
printf("SIGUSR1 received\n");
}
else if (signum == SIGUSR2)
{
printf("SIGUSR2 received\n");
}
else
{
printf("signal %d received\n", signum);
}
}
int main(void)
{
char buf[512];
int n;
struct sigaction sa_usr;
sa_usr.sa_flags = 0;
sa_usr.sa_handler = sig_usr; //信号处理函数
sa_usr.sa_flags=SA_RESTART;
sigaction(SIGUSR1, &sa_usr, NULL);
sigaction(SIGUSR2, &sa_usr, NULL);
printf("My PID is %d\n", getpid());
while (1)
{
if ((n = read(STDIN_FILENO, buf, 511)) == -1)
{
if (errno == EINTR)
{
printf("read is interrupted by signal\n");
}
}
else
{
buf[n] = '\0';
printf("%d bytes read: %s\n", n, buf);
}
}
return 0;
}
2 第一个终端运行
[root@localhost test]# g++ -o test test.cpp
[root@localhost test]# ./test
My PID is 2087
3 第二个终端运行
[root@localhost ~]# kill -USR1 2087
4 第一个终端结果
SIGUSR1 received
5 比较
比较这两个例子的结果,体会sa_usr.sa_flags=SA_RESTART;的含义。
SA_RESTART:被信号中断的系统调用会自行重启,因此没有read is interrupted by signal打印。