1. sigprocmask函数提供屏蔽和解除屏蔽信号的功能。 
从而实现关键代码的运行不被打断。 
函数声明如下:

int sigprocmask(int how, const sigset_t *set, sigset_t *oldset);
其中参数 how可设置的参数为:SIG_BLOCK, SIG_UNBLOCK,SIG_SETMASK 
SIG_BLOCK: 
按照参数 set 提供的屏蔽字,屏蔽信号。并将原信号屏蔽保存到oldset中。 
SIG_UNBLOCK: 
按照参数 set 提供的屏蔽字进行信号的解除屏蔽。针对Set中的信号进行解屏。 
SIG_SETMASK: 
按照参数 set 提供的信号设置重新设置系统信号设置。

2. 信号屏蔽与解屏常见实现 
方法一: SIG_BLOCK, SIG_UNBLOCK成对实现 
优点oldset可以不管。

方法二: 
SIG_BLOCK设置屏蔽,保存原有信号设置。 
SIG_SETMASK重新恢复原有设置。

3. 屏蔽过程中接受到的信号如何处理 
在信号屏蔽过程中,出现的所有被屏蔽的信号,不管发生多少次,在信号解除屏蔽后,系统会执行一次被屏蔽信号上的操作。

#include<stdio.h>
#include<signal.h>
#include<unistd.h> int flag_sigusr1 = 0;
int flag_sigusr2 = 0; void sig_usr1(int signo)
{
fprintf(stdout, "caught SIGUSR1\n");
flag_sigusr1 = 1;
return;
} void sig_usr2(int signo)
{
fprintf(stdout, "caught SIGUSR2\n");
flag_sigusr2 = 1;
return;
} int main(void){
sigset_t newmask, oldmask;
signal(SIGUSR1, sig_usr1);
signal(SIGUSR2, sig_usr2); fprintf(stdout, "catch sigusr1 can break\n"); while(1)
{
if(flag_sigusr1)
{
fprintf(stdout, "break\n");
break;
}
sleep(5);
}
fprintf(stdout, "first while was broken\n"); //重新设置为0
flag_sigusr1 = 0;
flag_sigusr2 = 0; // block SIGUSR1
sigemptyset(&newmask);
sigaddset(&newmask, SIGUSR1);
if(sigprocmask(SIG_BLOCK, &newmask, &oldmask) < 0)
{
perror("sigprocmask error");
} fprintf(stdout, "only catch sigusr2 can break, because sigusr1 has been blocked\n");
while(1)
{
if(flag_sigusr1 || flag_sigusr2)
{
fprintf(stdout, "break\n");
break;
}
sleep(5);
}
fprintf(stdout, "second while was broken\n"); fprintf(stdout, "after second while was broken, flag_sigusr1=%d, flag_sigusr2=%d\n", flag_sigusr1, flag_sigusr2); return 0;
}

  

多线程情况下每个线程共用信号处理函数,但是每个线程可以选择自己是否block某个信号。

再看一个多线程的例子:子线程的功能同上,主线程接收到hup信号会向子线程发送usr2信号。

#include<stdio.h>
#include<signal.h>
#include<unistd.h>
#include<pthread.h> int flag_sigusr1 = 0;
int flag_sigusr2 = 0;
int flag_sighup = 0; void sig_usr1(int signo)
{
fprintf(stdout, "sig|caught SIGUSR1\n");
flag_sigusr1 = 1;
return;
} void sig_usr2(int signo)
{
fprintf(stdout, "sig|caught SIGUSR2\n");
flag_sigusr2 = 1;
return;
} void sig_hup(int signo)
{
fprintf(stdout, "sig|caught SIGHUP\n");
flag_sighup = 1;
return;
} void *thread_control_signal(void *arg)
{
sigset_t newmask, oldmask;
sigemptyset(&newmask); //thread block sighup
sigemptyset(&newmask);
sigaddset(&newmask, SIGHUP);
if(pthread_sigmask(SIG_BLOCK, &newmask, &oldmask) < 0)
{
perror("sigprocmask error");
} fprintf(stdout, "thread|first while. catch sigusr1 or sigusr2 can break\n");
while(1)
{
if(flag_sigusr1 || flag_sigusr2)
{
fprintf(stdout, "thread|break\n");
break;
}
sleep(5);
}
flag_sigusr1 = 0; //thread block SIGUSR1
sigaddset(&newmask, SIGUSR1);
if(pthread_sigmask(SIG_BLOCK, &newmask, &oldmask) < 0)
{
perror("sigprocmask error");
} fprintf(stdout, "thread|first while. catch sigusr2 can break\n");
while(1)
{
if(flag_sigusr1 || flag_sigusr2)
{
fprintf(stdout, "break\n");
break;
}
sleep(10);
}
fprintf(stdout, "thread|thread exit\n");
return (void *)0;
} int main()
{
sigset_t newmask;
pthread_t tid;
int signo; //signal action
signal(SIGUSR1, sig_usr1);
signal(SIGUSR2, sig_usr2);
signal(SIGHUP , sig_hup); if(pthread_create(&tid, NULL, thread_control_signal, NULL) < 0)
{
perror("create pthread failed");
return -1;
} //main thread block sigusr1
sigemptyset(&newmask);
sigaddset(&newmask, SIGUSR1);
if(pthread_sigmask(SIG_BLOCK, &newmask, NULL) < 0)
{
perror("sigprocmask error");
} //main thread wait sighup
sigemptyset(&newmask);
sigaddset(&newmask, SIGHUP);
if(sigwait(&newmask, &signo) < 0)
{
perror("sigwait failed");
return -1;
}
fprintf(stdout, "main|get SIGHUP\n"); pthread_kill(tid, SIGUSR2);
pthread_kill(tid, SIGUSR2);
pthread_join(tid, NULL); fprintf(stdout, "main|exit\n");
return 0;
}

  

kill函数向进程发送信号,pthread_kill用于向线程发送信号。

Linux--信号阻塞与屏蔽的更多相关文章

  1. linux信号--阻塞与未决

    执行信号的处理动作称为信号递达(Delivery),信号从产生到递达之间的状态,称为信号未决(Pending). 进程可以选择阻塞(Block)某个信号.被阻塞的信号产生时将保持在未决状态,直到进程解 ...

  2. Linux 信号详解五(信号阻塞,信号未决)

    信号在内核中的表示 执行信号的处理动作成为信号递达(Delivery),信号从产生到递达之间的状态称为信号未决(Pending).进程可以选择阻塞(Block)某个信号. 被阻塞的信号产生时将保持在未 ...

  3. Linux信号-信号集&信号屏蔽字&捕捉信号【转】

    转自:https://blog.csdn.net/Lycorisradiata__/article/details/80096203 一. 阻塞信号 1. 信号的常见其他概念    实际执行信号的处理 ...

  4. linux系统编程之信号(五):信号集操作函数,信号阻塞与未决

    一,信号集及相关操作函数 信号集被定义为一种数据类型: typedef struct { unsigned long sig[_NSIG_WORDS]: } sigset_t 信号集用来描述信号的集合 ...

  5. Linux 信号详解六(可靠信号与不可靠信号)

    #include <stdio.h> #include <stdlib.h> #include <string.h> #include <unistd.h&g ...

  6. Linux信号(signal) 机制分析

    Linux信号(signal) 机制分析 [摘要]本文分析了Linux内核对于信号的实现机制和应用层的相关处理.首先介绍了软中断信号的本质及信号的两种不同分类方法尤其是不可靠信号的原理.接着分析了内核 ...

  7. [置顶] Linux信号相关笔记

    最近又温习了一遍Linux中的信号知识,发现有很多东西以前没有注意到,就通过这篇博客记录一下,巩固一下知识点. 一,信号基础: 信号是什么?为了回答这个问题,首先要从异常说起,这里的异常不是指c++/ ...

  8. 非常好的一篇对linux信号(signal)的解析 (转载)【转】

    转自:https://blog.csdn.net/return_cc/article/details/78845346 Linux信号(signal) 机制分析 转载至:https://www.cnb ...

  9. Linux 信号:signal 与 sigaction

    0.Linux下查看支持的信号列表: france@Ubuntux64:~$ kill -l ) SIGHUP ) SIGINT ) SIGQUIT ) SIGILL ) SIGTRAP ) SIGA ...

  10. Linux信号(signal)机制【转】

    转自:http://gityuan.com/2015/12/20/signal/ 信号(signal)是一种软中断,信号机制是进程间通信的一种方式,采用异步通信方式 一.信号类型 Linux系统共定义 ...

随机推荐

  1. 如何优雅打印nginx header和body

    场景 参考https://segmentfault.com/a/1190000000606867可以获取response的报文体,由于业务测试有获取响应头Header或响应体Body的需求,这里是通过 ...

  2. php时间戳与日期转换

    日期转换为时间戳 PHP 提供了函数可以方便的将各种形式的日期转换为时间戳,该类函数主要是: strtotime():将任何英文文本的日期时间描述解析为时间戳. mktime():从日期取得时间戳. ...

  3. robots.txt、humans.txt、.editorconfig、.gitignore、LICENSE.txt、README.md、CHANGLOG.md

    robots.txt搜索引擎查看的时候会查看这个文件,告诉搜索引擎哪些文件可以查看,哪些文件不能查看 当搜索引擎搜索网站的时候,会看有这个文件没,如果有,会通过里面的文件来确定哪些文件能看,哪些文件不 ...

  4. MVC,MVP和MVVM的区别

     MVC   转载标名出处  dub 从这幅图可以看到,我们可以看到在MVC里,View是可以直接访问Model的!从而,View里会包含Model信息,不可避免的还要包括一些业务逻辑. 在MVC模型 ...

  5. ES6 模块与 CommonJS 模块的差异

    ES6 模块与 CommonJS 模块完全不同.它们有两个重大差异 CommonJS 输出是值的拷贝,即原来模块中的值改变不会影响已经加载的该值,ES6静态分析,动态引用,输出的是值的引用,值改变,引 ...

  6. MySql数据库细节使用规范

    一.基础规范 (1)必须使用InnoDB存储引擎 解读:支持事务.行级锁.并发性能更好.CPU及内存缓存页优化使得资源利用率更高 (2)必须使用UTF8字符集 解读:万国码,无需转码,无乱码风险,节省 ...

  7. PHP中嵌套函数被调用时出现报错的问题

    对于初入门的PHP新手来说,在学习关于PHP函数嵌套的知识点时可能会有一定的难度.比如有的朋友在练习PHP函数嵌套相关问题时,会遇到调用内部函数时就会出现报错的情况等. 那么本篇文章就为大家详细得分析 ...

  8. pytest七:assert

    断言是写自动化测试基本最重要的一步,一个用例没有断言,就失去了自动化测试的意义了.什么是断言呢?简单来讲就是实际结果和期望结果去对比,符合预期那就测试 pass,不符合预期那就测试 failed py ...

  9. python接口自动化测试八:更新Cookies、session保持会话

    s = requests.session() # 此方法只适用于网站是cookies这种,网站是token的没用 # 这样做的好处就是可以保存cookies并保持会话,不用每次都去获取.传参 Toke ...

  10. extern "C" 回顾

    引入:在测试"extern "C" 与gcc, g++无关"时,使用到了extern "C"的概念,网上找篇文章回顾一下. 试验如下: te ...