可重入函数
可重入函数:函数可以由多个任务并发使用, 而不必担心数据错误
编写可重入函数:
不使用( 返回) 静态的数据、全局变量( 除非用信号量互斥)
不调用动态内存分配、 释放的函数
不调用任何不可重入的函数( 如标准 I/O 函数)
注:
即使信号处理函数使用的都是可重入函数( 常见的可重入函数),也要注意进入处理函数时,首先要保存 errno的值,结束时,再恢复原值。 因为 信号处理过程中,errno 值随时可能被改变
常见的可重入函数列表:
信号集
信号集概述
一个用户进程常常需要对多个信号做出处理
为了方便对多个信号进行处理, 在 Linux 系统中引入了信号集
信号集:表示多个信号的数据类型
信号集数据类型
sigset_t
sigemptyset 函数
#include <signal.h>
/*
* 功能:
* 初始化由 set 指向的信号集,清除其中所有的信号即初始化一个空信号集
* 参数:
* set:信号集标识的地址,以后操作此信号集,对 set 进行操作就可以
* return:
* 成功:0
* 失败:-1
*/
int sigemptyset(sigset_t *set)
sigfillset 函数
#include <signal.h>
/*
* 功能:
* 初始化信号集合 set, 将信号集合设置为所有信号的集合
* 参数:
* 信号集标识的地址, 以后操作此信号集,对 set 进行操作就可以
* return:
* 成功: 0
* 失败: -1
*/
int sigfillset(sigset_t *set);
sigismember函数
#include <signal.h>
/*
* 功能:
* 查询 signum 标识的信号是否在信号集合 set 之中
* 参数:
* set: 信号集标识符号的地址
* signum: 信号的编号
* return:
* 在信号集中返回 1,不在信号集中返回 0
* 错误, 返回 -1
*/
int sigismember(const sigset_t *set, int signum);
sigaddset函数
#include <signal.h>
/*
* 功能:
* 将信号 signum 加入到信号集合 set 之中
* 参数:
* set: 信号集标识的地址
* signum: 信号的编号
* return:
* 成功返回 0
* 失败返回 -1
*/
int sigaddset(sigset_t *set, int signum);
sigdelset函数
#include <signal.h>
/*
* 功能:
* 将 signum 所标识的信号从信号集合 set 中删除
* 参数:
* set:信号集标识的地址
* signum: 信号的编号
* return:
* 成功: 0
* 失败: -1
*/
int sigdelset(sigset_t *set, int signum);
创建一个空的信号集合, 向集合中添加信号, 判断集合中是否有这个信号
#include <signal.h>
#include <stdio.h>
int main(int argc, char *argv[])
{
sigset_t set;
int ret = 0;
sigemptyset(&set);
ret = sigismember(&set, SIGINT);
if(0 == ret)
{
printf("SIGINT is not a member of sigprocmask \nret = %d \n",ret);
}
sigaddset(&set, SIGINT);
sigaddset(&set, SIGQUIT);
ret = sigismember(&set, SIGINT);
if(1 == ret)
{
printf("SIGINT is a member of sigprocmask \nret = %d\n",ret);
}
return 0;
}
打印:
信号阻塞集(屏蔽集、 掩码)
每个进程都有一个阻塞集,它用来描述哪些信号递送到该进程的时候被阻塞
(在信号发生时记住它,直到进程准备好时再将信号通知进程)
所谓阻塞并不是禁止传送信号, 而是暂缓信号的传送。若将被阻塞的信号从信号阻塞集中删除, 且对应的信号在被阻塞时发生了, 进程将会收到相应的信号
sigprocmask 函数
#include <signal.h>
/*
* 功能:
* 检查或修改信号阻塞集,根据 how 指定的方法对进程的阻塞集合进行修改
* 新的信号阻塞集由 set 指定,而原先的信号阻塞集合由 oldset 保存
* 参数:
* how: 信号阻塞集合的修改方法
* SIG_BLOCK:向信号阻塞集合中添加 set 信号集
* SIG_UNBLOCK:从信号阻塞集合中删除 set 集合
* SIG_SETMASK:将信号阻塞集合设为 set 集合
* set: 要操作的信号集地址
* oldset: 保存原先信号集地址
* 注:若 set 为 NULL,则不改变信号阻塞集合,函数只把当前信号阻塞集合保存到 oldset 中
* return:
* 成功: 0
* 失败: -1
*/
int sigprocmask(int how, const sigset_t *set, sigset_t *oldset);
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <signal.h>
int main(int argc, char *argv[])
{
sigset_t set;
int i = 0;
sigemptyset(&set);
sigaddset(&set, SIGINT);
while(1)
{
sigprocmask(SIG_BLOCK, &set, NULL);
for(i = 0; i < 2; i++)
{
printf("SIGINT signal is blocked\n");
sleep(1);
}
sigprocmask(SIG_UNBLOCK, &set, NULL);
for(i = 0; i< 2; i++)
{
printf("SIGINT signal unblocked\n");
sleep(1);
}
}
return 0;
}
打印: