linux进程中对信号的屏蔽,linux进程中的信号屏蔽
在linux的进程中可以接收到各种的信号,并且如果你不对信号进行处理,linux中的进程就会采用默认的处理方式处理,比如ctrl-c的信号,进程对它的处理就是终止进程的执行。
在linux中,我们也可以在进程中屏蔽掉某些信号,使进程不去处理这些信号,但其中的SIGKILL和SIGSTOP是不能被阻塞的。
在这里先介绍几个信号的函数:
int sigempty(sigset_t *set); // 清空信号集set
int sigfillset(sigset_t *set); // 填满信号集,即让set包含所有的信号
int sigaddset(sigset_t *set, int signo); // 在set中增加signo信号
int sigdelset(sigset_t *set, int signo); // 在set中去掉signo信号
int sigismember(sigset_t *set, int signo); // 信号signo是否在信号集set中
int sigprocmask(int how, const sigset_t set, sigset_t oset); // 若oset非空,则进程的当前信号屏蔽字通过oset返回,若set是一个非空指针,着参数how指示如何修改当前信号的屏蔽字,how可以取三个值:
SIG_BLOCK:增加一个信号。
SIG_UNBLOCK:解除一个信号。
SIG_SETMASK:该进程的信号将被set信号集取代。
int sigpengding(sigset_t *set); // 该函数返回信号集,该信号通过set参数返回。
以上函数都在#include 头文件中。
下面用《unix环境高级编程》里的一个例子说明一下,代码有所修改,先看代码(main.c,里面有个人对代码的注释):
view plaincopy to clipboardprint?
#include
#include
#include
static void sig_quit(int);
int
main(void)
{
sigset_t newmask, oldmask, pendingmask;
//设置对信号SIGQUIT的处理函数
if (signal(SIGQUIT, sig_quit) == SIG_ERR)
{
fprintf(stderr, "can't catch SIGQUIT/n");
exit(1);
}
//设置一个空的信号集
sigemptyset(&newmask);
sigaddset(&newmask, SIGQUIT); // 在这个信号集中增加SIGQUIT信号
//在当前进程中增加newmask信号集作为屏蔽信号集,oldmask返回当前进程的信号集
if (sigprocmask(SIG_BLOCK, &newmask, &oldmask) < 0)
{
fprintf(stderr, "SIG_BLOCK error/n");
exit(1);
}
sleep(5);
//返回当前进程信号集
if (sigpending(&pendingmask) < 0)
{
fprintf(stderr, "sigpending error/n");
exit(1);
}
//检查SIGQUIT信号是否在当前信号集中
if (sigismember(&pendingmask, SIGQUIT))
printf("/nSIGQUIT pending/n");
//恢复进程的信号集
if (sigprocmask(SIG_SETMASK, &oldmask, NULL) < 0)
{
fprintf(stderr, "SIG_SETMASK error/n");
exit(1);
}
printf("SIGQUIT unblocked/n");
sleep(5);
exit(0);
}
static void sig_quit(int signo)
{
printf("caught SIGQUIT/n");
//恢复进程对SIGQUIT的默认处理
if (signal(SIGQUIT, SIG_DFL) == SIG_ERR)
{
fprintf(stderr, "can't reset SIGQUIT/n");
exit(0);
}
}
#include
#include
#include
static void sig_quit(int);
int
main(void)
{
sigset_t newmask, oldmask, pendingmask;
//设置对信号SIGQUIT的处理函数
if (signal(SIGQUIT, sig_quit) == SIG_ERR)
{
fprintf(stderr, "can't catch SIGQUIT/n");
exit(1);
}
//设置一个空的信号集
sigemptyset(&newmask);
sigaddset(&newmask, SIGQUIT); // 在这个信号集中增加SIGQUIT信号
//在当前进程中增加newmask信号集作为屏蔽信号集,oldmask返回当前进程的信号集
if (sigprocmask(SIG_BLOCK, &newmask, &oldmask) < 0)
{
fprintf(stderr, "SIG_BLOCK error/n");
exit(1);
}
sleep(5);
//返回当前进程信号集
if (sigpending(&pendingmask) < 0)
{
fprintf(stderr, "sigpending error/n");
exit(1);
}
//检查SIGQUIT信号是否在当前信号集中
if (sigismember(&pendingmask, SIGQUIT))
printf("/nSIGQUIT pending/n");
//恢复进程的信号集
if (sigprocmask(SIG_SETMASK, &oldmask, NULL) < 0)
{
fprintf(stderr, "SIG_SETMASK error/n");
exit(1);
}
printf("SIGQUIT unblocked/n");
sleep(5);
exit(0);
}
static void sig_quit(int signo)
{
printf("caught SIGQUIT/n");
//恢复进程对SIGQUIT的默认处理
if (signal(SIGQUIT, SIG_DFL) == SIG_ERR)
{
fprintf(stderr, "can't reset SIGQUIT/n");
exit(0);
}
}
编译: gcc main.c
生成:a.out
运行:./a.out
输出如下(ubuntu9.10):
^/
SIGQUIT pending
caught SIGQUIT
SIGQUIT unblocked
^/退出
下面解释一下输出:
^/ 在第一次sleep(5)的5秒中内产生信号一次(按ctrl+/)
SIGQUIT pending 从sleep返回后
caught SIGQUIT 在信号处理函数中
SIGQUIT unblocked 从sigprocmask返回后
^/退出 再次产生信号
我们对着程序来看下输出。
在我们设置SIGQUIT屏蔽字和恢复进程的信号集这段时间,我们产生的SIGQUIT信号,我们的进程并没去处理,所以输出了SIGQUIT pending 。
在我们恢复进程的信号集后,我们进程就扑捉到了我们刚才产生的信号,因而就输出了caught SIGQUIT,在sig_quit函数中,我们恢复了SIGQUIT的默认处理方式(即终止进程运行),进程当我们再次产生SIGQUIT信号,进程就退出了。
当我们产生进程时,一些unix系统会对进程中要处理的信号进行排队,我们的进程会对信号队列中的信号进行处理。我们再运行一下刚才的程序,在第一次sleep(5)的5秒中内产生信号10次信号,看下会怎么样,下面是我的输出:
^/^/^/^/^/^/^/^/^/^/
SIGQUIT pending
caught SIGQUIT
SIGQUIT unblocked
^/退出
下面解释一下输出:
^/^/^/^/^/^/^/^/^/^/ 在第一次sleep(5)的5秒中内产生信号10次信号
SIGQUIT pending 从sleep返回后
caught SIGQUIT 从sigprocmask返回后
SIGQUIT unblocked 从sigprocmask返回后
^/退出 再次产生信号
这里可以看到linux系统对没有对信号进行排队,产生10次信号,只处理一次。
在上面的例子中,我们用signal函数来指定信号的处理函数,用sigprocmask来指定信号屏蔽字,其实这些都可以在一个函数中解决,它就是sigaction ,推荐使用sigaction函数。
pthread_sigmask与sigprocmask。前者是线程安全的。
pthread_sigmask改变的是线程的信号集与整个进程无关。
linux进程中对信号的屏蔽,linux进程中的信号屏蔽相关推荐
- 如何在Linux中查看所有正在运行的进程
你可以使用ps命令.它能显示当前运行中进程的相关信息,包括进程的PID.Linux和UNIX都支持ps命令,显示所有运行中进程的相关信息.ps命令能提供一份当前进程的快照.如果你想状态可以自动刷新,可 ...
- linux进程看门狗使用方式,Linux系统中基于看门狗的精细化进程监控方法及系统的制作方法...
Linux系统中基于看门狗的精细化进程监控方法及系统的制作方法 [技术领域] [0001] 本发明涉及Linux系统的进程监控技术领域,特别是涉及一种Linux系统中基于看 门狗的精细化进程监控方法及 ...
- linux进程跑飞了,【Shell】Linux信号(二)
[信号产生] bash shell允许用键盘上的键组合生成两种基本的Linux信号,这个在你需要停止或暂停跑飞了的程序时就能派上用场. 终止进程 Ctrl+C组合键会生成SIGINT信号,并将其发送给 ...
- linux wait函数头文件_第五十八章、linux中的3种正常结束进程的方式你都了解么...
在前两章中我们了解了创建进程,这一章我们来了解下,在linux下怎么结束进程. 在linux中,有3种正常结束进程的方法和2种异常终止的方法: 1. 正常结束: a. 在main函数中调用return ...
- Linux进不了进程,既然在Linux中程序不是进程,那么到底什么才算是进程呢?
C语言程序员编写的代码可以编译为程序,程序通常存放在磁盘等存储介质中.在 Linux 中,处于运行期的程序被称作"进程". 处于运行期的程序被称作"进程" 进程 ...
- linux mysql 进程查看工具_linux查看正在运行的进程(如何在Linux中查看所有正在运行的进程)...
如何在Linux中查看所有正在运行的进程 名称:ps 使用权限:所有使用者 使用方式:ps [options] [--help] 说明:显示瞬间行程 (process) 的动态 参数:ps的参数非常多 ...
- 【Linux操作系统基础】第六章 Linux中的进程管理
一.进程及其状态 程序是静态的代码文件,没有生命周期.进程是指程序运行时的形态,是程序的一个副本,进程有生命周期(准备期,运行期,终止期) 进程是资源调用的最小单位,系统中的资源在同一时间只能被同一个 ...
- linux查询某域线程是否满了,Linux多线程编程的时候怎么查看一个进程中的某个线程是否存活...
pthread_kill: 别被名字吓到,pthread_kill可不是kill,而是向线程发送signal.还记得signal吗,大部分signal的默认动作是终止进程的运行,所以,我们才要用sig ...
- linux系统怎么结束程序,如何在 Linux 系统中结束进程或是中止程序
如何在 Linux 系统中结束结束进程或是中止程序 进程出错的时候,您可能会想要中止或是中断这个进程.本文,我们将在命令行和图形界面中探索进程或是应用程序的中断,这里我们使用 gedit 作为样例程序 ...
最新文章
- 如何加入家庭组计算机打印机,如何使用利用win7家庭组打印机
- 别总埋汰写代码,停下总结一下吧
- Libsvm的一些说明帮助吧
- CSS页面重构“鑫三无准则”之“无图片”准则——张鑫旭
- phpstudy运行PHP项目出现404怎么办?
- 如何将一个完整项目推到码云_怎么将本地项目放到码云(gitee)上面?图文详解
- java按年月季度统计折线图_拆线图按年、按月,按天统计,前端传时间只要起始时间与结束时间...
- 史上最强Dubbo面试26题和答案:核心组件+服务治理+架构设计等
- hdu1426 Sudoku Killer dfs
- 新塘单片机烧写器_新唐MCU常用的工具软件
- FFMPEG 编解码失败 non-existing PPS 0 referenced
- 为什么计算机打不开优盘,U盘打不开,且8G的U盘只报64M,为什么?
- 如何从程序员升级到架构师?
- 英文标点符号unicode
- 爬虫实战 | 爬取东方财富网股票数据
- 计算机三级嵌入式工程师,怎样通过计算机三级嵌入式,如何成为嵌入式工程师——第一章嵌入式系统概论
- 【算法记录】梅式砝码问题
- Maya动画——使用诺亦腾惯性动捕设备进行动作捕捉的方法
- AC自动机笔记与例题整理
- 如何科学地进行A_B实验
热门文章
- 怎样在Linux系统中编译,Linux操作系统如何编译程序?
- 北京内推 | 微软亚洲研究院MSRA STCA招聘多模态算法实习生
- RUN++ | 对比学习加持,多轮对话改写新SOTA!
- 预训练图像处理Transformer:刷榜多项底层视觉任务
- 基于多域连接卷积神经网络的精神分裂症脑功能网络分类
- AIProCon在线大会笔记之张钹院士:探索第三代人工智能,需要勇闯无人区的人才!
- MySQL学习第三章练习题
- 如何自动填充网页表单_iCab for Mac(web网页浏览器)
- 十大经典排序算法总结(够兄弟们喝一壶的)
- 数据结构和算法之稀疏数组