Linux—信号阻塞与信号未决(day10)

目录

一、信号阻塞与信号未决

二、pause(2)的使用

三、信号传送过程处理

四、可重入函数

五、编写代码实现信号处理函数的继承

六、setitimer实现定时器


一、信号阻塞与信号未决

  进程可以对某个信号设置阻塞或屏蔽,可是使用sigset_t(信号集)这个数据类型进行操作,对sigset_t操作的函数函数:

  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);
  int sigaction( int sig, const struct sigaction *act,struct sigaction *oact );
  
  各个函数对应的功能如下:
  sigemptyset(sigset_t *set)初始化由set指定的信号集,信号集里面的所有信号被清空;
  sigfillset(sigset_t *set)调用该函数后,set指向的信号集中将包含linux支持的64种信号;
  sigaddset(sigset_t *set, int signum)在set指向的信号集中加入signum信号;
  sigdelset(sigset_t *set, int signum)在set指向的信号集中删除signum信号;
  sigismember(const sigset_t *set, int signum)判定信号signum是否在set指向的信号集中。
  int sigaction( int sig, const struct sigaction *act,struct sigaction *oact )检查、修改和指定信号相关联的信号响应。
 
sigset操作函数
 
#include<signal.h> 
 
 
int sigemptyset(sigset_t *set);
功能:
  将信号集清空
参数:
  指定要清空的信号集
返回值:
  成功:0
  错误:-1
 
 
sigfillset(sigset_t *set)
功能:
  将信号集置为满
参数:
   set:指定要置满的信号集
返回值:
 
  成功:0
  错误:-1
 
 
int sigaddset(sigset_t *set, int signum);
功能:
  给信号集添加信号
参数:
   set:指定信号集
  signum:指定添加信号
返回值:
  成功:0
  错误:-1
 
 
  int sigdelset(sigset_t *set, int signum);
功能:
  删除指定信号
参数:
   set:指定信号集
  signum:指定删除信号
返回值:
  成功:0
  错误:-1
 
 
int sigismember(const sigset_t *set, int signum);
功能:
  测试信号是否为指定信号集成员
参数:
   set:指定信号集
  signum:指定信号
返回值:
  错误:-1
  否:0
  有:1
 

设置解除阻塞
  设置对2号信号进行阻塞:
1、定义sigset_t block_set信号集
2、将block_set信号集所有成员清空
3、将2号信号添加到block_set信号集中
4、将block_set设置为这个进程的阻塞信号集
如何将信号集设置为阻塞:使用sigprocmask(2)函数,包含头文件#include <signal.h>     。

执行信号的处理动作称为信号递达(Delivery),信号从产生到递达之间的状态,称为信号未决(Pending)。

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

         
int sigprocmask(int how,const sigset_t*set,sigset_t *oldset);   
功能:
  检测活泼改变阻塞信号
参数:
     how:用于指定信号修改的方式,可能选择有三种

       SIG_BLOCK//将set所指向的信号集中包含的信号加到当前的信号掩码中。即信号掩码和set信号集进行或操作。

            SIG_UNBLOCK//将set所指向的信号集中包含的信号从当前的信号掩码中删除。即信号掩码和set进行与操作。

       SIG_SETMASK //将set的值设定为新的进程信号掩码。即set对信号掩码进行了赋值操作。

    set:为指向信号集的指针,在此专指新设的信号集,如果仅想读取现在的屏蔽值,可将其置为NULL。

    oldset:也是指向信号集的指针,在此存放原来的信号集。可用来检测信号掩码中存在什么信号。


返回值:   成功执行时,返回0。失败返回-1,errno被设为EINVAL。

例:实现对2号信号的阻塞
#include<stdio.h>
#include<signal.h>

int main(void){
    signal_t block;
    //将block集合清空
    sigemptyset(&block);
    //将2号信号添加到block集合中
    sigaddset(&block,SIGINT);
    //将block设置为阻塞信号集
    sigprocmask(SIG_SETMASK,&block,NULL);
    while(1);
    return 0;
} 

 1、对阻塞信号解除

  信号可以分为可靠信号和不可靠信号,多个相同的不可靠信号(1-31),只会响应一个,其他会丢失。可靠信号(34-64)的每一信号都会被响应。

#include<stdio.h>
#include<signal.h>

int main(void){
    signal_t block;
    //将block集合清空
    sigemptyset(&block);
    //将2号信号添加到block集合中
    sigaddset(&block,SIGINT);//此处为不可靠信号
    //将block设置为阻塞信号集
    sigprocmask(SIG_SETMASK,&block,NULL);
    sleep(10);
    sigprocmask(SIG_UNBLOCK,&block,NULL);
    return 0;
} 

 2、信号阻塞,查看未决信号

使用sigpending(2)查看
sigpending(2)
#include<signal.h>
int sigpending(sigset_t set);
功能:
  检测未决信号
参数:
  set:值-结果参数,用于返回进程的未决信号
返回值:
  成功:0
  错误:-1
例,检测未决信号
#include<stdio.h>
#include<signal.h>

int main(void){
    signal_t b,p;
    //将b集合清空
    sigemptyset(&b);
    //将2号信号添加到b集合中
    sigaddset(&b,SIGINT);//此处为不可靠信号
    //将b设置为阻塞信号集
    sigprocmask(SIG_SETMASK,&b,NULL);
    while(1){
        sleep(1);
        sigemptyset(&p);
        sigpending(&p)
        //检测信号
        int f=sigismember(&p,2);
        if(f==-1){
            perror("sigismember");
            return 1; 
        }
        if(f==0){
            printf("no 2
");
        }else{
            printf("pending 2
");
        }
    }
    return 0;
}     
int sigsuspend(const sigset_t*sigmask);

五、编写代码实现信号处理函数的继承

略,子进程可以继承父进程的信号处理函数。
 
 
 
原文地址:https://www.cnblogs.com/ptfe/p/11020493.html