用到的信号函数和有关信号的东西
异步:
一种通讯方式,对设备要求简单。我们的PC机提供的标准通讯接口都是异步的。
异步双方不需要共同的时钟,也就是接收方不知道发送方什么时候发送,所以在发送的信息中要有提示接收方开始接受的信息,如开始位,同时在结束时有停止位。
异步的另一种含义:计算机多线程的异步处理。与同步处理相对,异步处理不用阻塞当前线程来等待处理完成,而是允许后续操作,直到其他线程将处理完成,并回调通知此线程。
信号的来源:
产生条件:硬件和软件
硬件:
- 终端上按下某些键,将产生信号。
- Ctrl+C产生一个SIGINT信号
- 硬件异常产生信号:
- 除数为0,无效的存储访问
- 这些事件通常由硬件(CPU)检测到,并将其通知给Linux操作系统内核,然后内核生成相应的信号,并把信号发送给该事件发生时正在运行的程序。
软件:
- 用户在终端下调用kill命令向进程发送任意信号
- 进程调用kill或sigqueue函数发送信号
- 当检测到某种软件条件已经具备时发出信号,如由alarm或settimer设置的定时器超时将生成SIGALRM信号
信号的种类
Linux系统下支持的信号种类有64种,定义在#include<signal.h>
中
在书上P221,很详细,就列出几个我用到的信号
信号:
SIGINT:用户按下了
<Ctrl+C>
组合键时,用户终端向正在运行中的由该终端启动的程序发出此信号,默认动作为终止此进程。SIGQUIT:用户按下
<Ctrl+\>
组合键时产生该信号,用户终端向正在运行中的由该终端启动的程序发出此信号,默认动作为终止进程并产生core文件。core文件是什么?
当我们程序崩溃时,内核有可能把该程序当前内存映射到core文件里,方便程序员找到程序找到出现问题的地方。
当一个程序崩溃时,在晋城当前工作目录的core文件中复制了该进程的存储图像。core文件仅仅是一个内存映像(同时加上调试信息),主要是用来调试的。
- SIGPIPE:向一个没有读端的管道写数据,默认动作为终止进程。
信号处理
signal
- 原型:
#include<signal.h> typedef void (*sighandler_t)(int); sighandler_t signal(int signum,sighandler_t handler);
作用:用来设置进程在接收到信号时的动作
参数:
根据signum指定的信号编号来设置该信号处理函数。
- 当指定的信号到达时就会跳转到参数handler指定的参数执行。
- 如果参数handler不是函数指针,则必须是常数SIG_IGN(忽略该信号)或SIG_DFL(对该信号执行默认操作)。
handler:一个函数指针,它所指向的函数的类型是sighandler_t,即它所指向的函数有一个int型的参数,且返回值的类型为void
-
执行情况 返回值 成功 返回以前的信号处理函数指针 失败 返回SIG_ERR(即-1) 注意:SIGKILL和SIGSTOP两个信号不能被捕捉或忽略
#include<stdio.h> #include<signal.h> /*信号处理函数*/ void handler_sigint(int signo) { printf("recv SIGINT\n"); } int main(void) { /*安装信号处理函数*/ signal(SIGINT,handler_sigint); while(1) { ; } return 0; }
![2018-08-14 17-12-04 的屏幕截图](/home/lala/图片/2018-08-14 17-12-04 的屏幕截图.png)
程序首先使用signal安装信号SIGINT的处理函数handler_sigint函数,然后进入死循环。当接收到信号时,程序自动跳转到信号处理函数处执行,打印出提示消息,然后返回主函数继续执行死循环。
信号屏蔽
POSIX标准定义了数据类型sigset_t来表示信号集,并且定义了一系列函数来操作信号集。
信号集
#include<signal.h>
int sigemptyset(sigset_t *set);
int sigfillset(sigset_t *set);
int sigaddset(sigset_t *set,int signum);
int sigdelset(sigset_t *set,int signum);
int sigismember(const sigset_t *set,int signum);
函数的具体含义:
- sigemptyset:用来初始化一个信号集,使其不包括任何信号。
- sigfillset:用来初始化一个信号集,使其包括所有信号。
- sigaddset:用来向set指定的信号集中添加由signum指定的信号。
- sigdelset:用来从set指定的信号集中删除由signum指定的信号。
- sigismember:用来测试信号signum是否包括在set指定的信号集中。
-
执行情况 返回值 成功 返回0 失败 返回-1 以上是除过sigismember的函数的执行情况
返回值 | 含义 |
---|---|
1 | 表示测试的信号在信号集中 |
0 | 表示测试的信号不在信号集中 |
上面这个是sigismember的函数的执行情况
信号屏蔽
信号屏蔽又称信号阻塞
#include<signal.h>
int sigprocmask(int how,const sigset_t *set,sigset_t *oldset);
int sigpending(sigset_t *set);
int sigsuspend(const sigset_t *mask);
函数解析:
sigprocmask函数;
每个进程都有一个信号屏蔽吗,它规定了当前阻塞而不能递送给该进程的信号集。调用函数可以监测或更改进程的信号屏蔽码。如果参数oldset是非空指针,则进程之前的信号屏蔽码通过oldset返回;如果set是非空指针,则函数将根据参数how来修改信号当前的屏蔽码。
- how:
how 含义 SIG_BLOCK 奖金诚信的信号屏蔽码设置为当前信号屏蔽码和set指向的信号集的并集 SIG_UNBLOCK 将进程新的信号屏蔽码设置为当前信号屏蔽码中,删除set所指向的信号集,即set包含了我们希望接触阻塞的信号。既是对当前信号屏蔽码中存在的信号使用SIG_UNBLOCK也是合法操作 SIG_SETMASK 将进程新的信号屏蔽码设置为set指向的值 执行情况 返回值 成功 0 失败 -1