可重入函数

   可重入函数:函数可以由多个任务并发使用, 而不必担心数据错误
          编写可重入函数:
                不使用( 返回) 静态的数据、全局变量( 除非用信号量互斥)
                不调用动态内存分配、 释放的函数
                不调用任何不可重入的函数( 如标准 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;
}

打印: