进程间通信之信号集函数组

信号在内核中的表示

  • 信号递达(Delivery):实际执行信号的处理动作。
  • 信号未决(Pending):信号从产生到递达之间的状态。
    进程可以选择阻塞(Block)某个信号(SIGKILL和 SIGSTOP不能被阻塞)。被阻塞的信号产生时将保持在未决状态,直到进程解除对此信号的阻塞,才执行递达的动作。
    注意:阻塞和忽略不同,只要信号被阻塞就不会递达,而忽略是在递达之后可选的一种处理动作。

信号集处理函数组

1.创建信号集合

函数 说明
int sigemptyset(sigset_t *set) 将set指向的信号集初始化为空
int sigfillset (sigset_t *set) 把信号集初始化为包含系统支持的所有信号
int sigaddset (sigset_t *set, int signum) 把信号signum添加到信号集set中
int sigdelset (sigset_t *set, int signum) 把信号signum从信号集set中删除
int sigismember (sigset_t *set, int signum) 判断给定信号signum是否是信号集的一个成员

注意:

  • 使用sigset_t类型的变量前,必须调用sigemptyset或sigfillset做初始化,使信号集处于确定状态。
  • 以上函数返回值(sigismember 若包含返回1,不包含返回0 )成功:0; 出错:-1

设置信号屏蔽

// Get and/or change the set of blocked signals 获取和/或更改阻塞信号集
extern int sigprocmask (int __how, const sigset_t *__restrict __set, sigset_t *__restrict __oset)

  1. how,有三个参数
参数值 含义
SIG_BLOCK 将 set 信号集合添加到当前进程的阻塞集合中
SIG_UNBLOCK 将 set 信号集合从当前进程的阻塞集合中删除
SIG_SETMASK 将 set 信号集合设置为当前进程的阻塞集合
  1. 如果oset非空,则读取进程的当前信号屏蔽字,通过oset参数传出
  2. 如果set非空,则更改进程的信号屏蔽字。
  3. 如果oset和set都是非空,则先将原来的信号屏蔽字备份到oset里,然后根据set和how参数更改信号屏蔽字。

检测信号

int sigpending(sigset_t *set);
函数作用:读取当前进程的未决信号集,通过set参数传出。包括已经到达但没有被处理的信号。成功调用返回0,否则返回-1,并设置errno表明错误原因。
注意:
当使用fork()函数时,子进程会继承父进程的信号语义,包括信号的屏蔽和处理,而未处理信号将被清空。

使用实例

#include 
#include 
#include 
#include 
#include 

/* 自定义的信号处理函数 */
void my_func(int sign_no) {
    if (sign_no == SIGINT) {
        printf("\nI have get SIGINT\n");
    } else if (sign_no == SIGQUIT) {
        printf("\nI have get SIGQUIT\n");
    }
}

int main() {
    sigset_t set, ignore;
    struct sigaction action;
    /* 初始化信号集为空 */
    if (sigemptyset(&set) < 0 || sigemptyset(&ignore) < 0) {
        perror("sigemptyset");
        exit(1);
    }
    /* 将相应的信号加入信号集 */
    if (sigaddset(&set, SIGQUIT) < 0 || sigaddset(&set, SIGINT) < 0) {
        perror("sigaddset");
        exit(1);
    }
    /* 检测相应的信号是否加入信号集 */
    sigemptyset(&action.sa_mask);
    action.sa_handler = my_func;
    action.sa_flags = 0;
    sigaction(SIGINT, &action, 0);
    sigaction(SIGQUIT, &action, 0);
    printf("programming is starting\n");
    pause();
    /* 设置信号集屏蔽字,此时 set 中的信号不会被传递给进程,暂时进入待处理状态 */
    if (sigprocmask(SIG_BLOCK, &set, 0) < 0) {
        perror("sigprocmask");
        exit(1);
    } else {
        printf("Signal set was blocked!\n");
    }
    printf("Please press Ctrl+c to test SIGINT...\n");
    sleep(3);
    //调用信号集函数测试SIGINT是否被屏蔽
    sigpending(&ignore);
    if (sigismember(&ignore, SIGINT)) {
        printf("\nThe SIGINT signal has been ignored");
    }
    //从信号SIGINT所在的信号集中删除SIGINT
    if (sigdelset(&set, SIGINT) < 0) {
        printf("sigdelset");
    }
    /* 在信号屏蔽字中删除 set 中的信号 */
    if (sigprocmask(SIG_UNBLOCK, &set, 0) == 0 && sigprocmask(SIG_UNBLOCK, &ignore, 0) == 0) {
        printf("Signal set is in unblock state\n");
    } else {
        perror("sigprocmask");
        exit(1);
    }
    pause();
}

进程间通信之信号集函数组_第1张图片

你可能感兴趣的:(Ubuntu)