信号
内核和用户空间通信,软件上对中断机制的模拟,异步通信
信号是内核产生
信号的发送(用户空间用kill( 信号, pid) 、 raise(信号))
捕获 ( SIG_IGN, 自定义的信号处理函数 ,SIG_DFL)
一些常用信号
SIGQUIT CTRL+\
SIGINT CTRL+C
SIGSTOP 暂停 --- 不能更改信号处理方式
SIGKILL 终止 --- 不能更改信号处理方式
SIGALRM alarm函数
SIGHUP 关闭终端的时候
SIGTSTP CTRL+Z
SIGCHLD --- 子进程结束时候
SIGPIPE --- 管道不能写的时候产生
信号处理函数
signal()---- 简单
sigaction () --- 信号集,功能比较强大,可以传送信号的信息signal(SIGINT , func);
struct sigaction *restrict old ;
---> sigaction (SIGINT , func , old);
old里面存放的是在该进程中sigint之前的信号处理函数, 这里可能就是SIG_DFL
sigemptyset() ---- 清空信号集
sigaddset ()(对应的信号集, 对应的信号值)--- 单独设置一个对应信号
sigfillset () ----- 直接设置信号集
sigdelset () ---- 从信号集里面删除其中一个信号
sigpending() ---- 判断信号是否屏蔽
sigsuspend() ---- 取消屏蔽
sigpromask () ---- 在进程某一个时间段去把一个信号屏蔽掉
sigaction() ---- 检测并修改信号处理 ,设置信号处理函数,保留之前的信号处理操作
实例:
#include <unistd.h>
#include <signal.h>
#include <sys/types.h>
#include <stdlib.h>
#include <stdio.h>
void handler(int sig)
{
printf("Handle the signal %d\n", sig);
}
int main()
{
sigset_t sigset;//用于记录屏蔽字
sigset_t ign;//用于记录被阻塞的信号集
struct sigaction act;
//清空信号集
sigemptyset(&sigset);
sigemptyset(&ign);
//向信号集中添加信号SIGINT
sigaddset(&sigset, SIGINT); // 2 对应修改第1位 (2 1 0) --1-
//向信号集中添加信号SIGQUIT
// sigaddset(&sigset, SIGQUIT); // 3 对应修改第2位 -1--
//设置处理函数和信号集
act.sa_handler = handler;
sigemptyset(&act.sa_mask);
act.sa_flags = 0;
sigaction(SIGINT, &act, 0); // signal函数传不了信号信息
printf("1st Wait the signal SIGINT...\n");
pause();//挂起进程,等待信号
//设置进程屏蔽字,在本例中为屏蔽SIGINT、SIGQUIT
sigprocmask(SIG_SETMASK, &sigset, 0);
printf("sigset = 0x%x \n",*(int *)(&sigset));
printf("Please press Ctrl+c in 10 seconds...\n");
sleep(10);
//测试有没有信号是否被屏蔽
sigpending(&ign); // 有没有信号处于pending
if(sigismember(&ign, SIGINT))// 如果屏蔽的信号里面有SIGINT
printf("The SIGINT signal has ignored\n");
else
printf("no SIGINT signal\n");
//在信号集中删除信号SIGINT
sigdelset(&sigset, SIGINT);
printf("2nd Wait the signal SIGINT...\n");
//将进程的屏蔽字重新设置,即取消对SIGINT、SIGQUIT的屏蔽
//并挂起进程
sigsuspend(&sigset);
printf("The app will exit in 5 seconds!\n");
sleep(5);
exit(0);
}