原创文章,转载请注明出处,谢谢!
作者:清林,博客名:飞空静渡
在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 <signal.h> 头文件中。
下面用《unix环境高级编程》里的一个例子说明一下,代码有所修改,先看代码(main.c,里面有个人对代码的注释):
- #include <signal.h>
- #include <stdio.h>
- #include <stdlib.h>
- 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函数。
-
相关博文推荐
- 关于引用和指针的问题
- ethtool小工具的源代码网址
- 第一篇
- vim配置文件
- Linux文件系统预读(二)
- Apache Prefork、Worke...
- Call to undefined fu...
- mysql_connect报告”No s...
暂无评论
核心技术类目
- 文章分类
- 阅读排行
- 4KB大扇区硬盘的性能分析(7557)
- QuickLZ -- 一个号称世界压缩速度最快的压缩库(7393)
- 手把手教你用WinHex在NTFS分区中恢复被删除的文件(上)(7247)
- QTableWidget的简单使用(6745)
- 关于编译glibc-2.9的These critical programs are missing or too old: as ld 错误(5861)
- 深入浅出linux内核源代码之双向链表list_head(上)(5584)
- C++11 FAQ中文版:std::function 和 std::bind(5157)
- udev(八):实战:使用udevadm修改usb优盘在/dev下的名字(4915)
- QT浏览器学习之一:QWebView(4729)
- QT中的pro文件的编写(4322)
- 评论排行
- NTFSRecover 1.3 全新改版(12)
- 深入浅出linux内核源代码之双向链表list_head(上)(9)
- 简易分析myicq的内存池模型(4)
- 深入浅出linux内核源代码之双向链表list_head(下)(3)
- ext4分区中恢复被删除的文件(3)
- QTreeWidget的简单使用(3)
- QT浏览器学习之一:QWebView(3)
- C++11 FAQ中文版:std::function 和 std::bind(3)
- 关于编译glibc-2.9的These critical programs are missing or too old: as ld 错误(3)
- 漂亮MM想嫁有钱人 金融家的回复令人叫绝(3)
- 推荐文章
- 最新评论
- C++11 FAQ中文版:std::function 和 std::bind
zzyoucan: std::function是c++新特性吗?
- C++11 FAQ中文版:std::function 和 std::bind
chenzhekl: 同楼上,Currying应该翻译成科里化
- QT浏览器学习之一:QWebView
小神000: 为啥我在ARM9上移植了你这个程序之后没法显示页面
- c++之指针作为函数参数传递的问题
小强茜茜: 很好,谢谢!
- gcc:预处理语句--#define、#error和#warning
weiweishuo: 写的够简明,谢了
- c++之指针作为函数参数传递的问题
qinchange: 很好很好
- 与重写代码作斗争
FirstHope: 非常有共鸣…………总觉得“写代码要比读代码要容易得多”最近在看高手写的代码,完全头脑发懵,很难坚持…...
- gcc:预处理语句--#define、#error和#warning
qianlong4526888: printf();后面的回车符怎么都是"/n"?!十分怀疑,这些代码lz测试过么?
- 手把手教你用WinHex在NTFS分区中恢复被删除的文件(上)
rogerchenzy: 楼主,在不?我有些问题想请教一下您。
- QTableWidget的简单使用
大帅爷: 感谢楼主的时间!清晰简明,非常适合初学者!
- 好友