在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进程中的信号屏蔽相关推荐

  1. 如何在Linux中查看所有正在运行的进程

    你可以使用ps命令.它能显示当前运行中进程的相关信息,包括进程的PID.Linux和UNIX都支持ps命令,显示所有运行中进程的相关信息.ps命令能提供一份当前进程的快照.如果你想状态可以自动刷新,可 ...

  2. linux进程看门狗使用方式,Linux系统中基于看门狗的精细化进程监控方法及系统的制作方法...

    Linux系统中基于看门狗的精细化进程监控方法及系统的制作方法 [技术领域] [0001] 本发明涉及Linux系统的进程监控技术领域,特别是涉及一种Linux系统中基于看 门狗的精细化进程监控方法及 ...

  3. linux进程跑飞了,【Shell】Linux信号(二)

    [信号产生] bash shell允许用键盘上的键组合生成两种基本的Linux信号,这个在你需要停止或暂停跑飞了的程序时就能派上用场. 终止进程 Ctrl+C组合键会生成SIGINT信号,并将其发送给 ...

  4. linux wait函数头文件_第五十八章、linux中的3种正常结束进程的方式你都了解么...

    在前两章中我们了解了创建进程,这一章我们来了解下,在linux下怎么结束进程. 在linux中,有3种正常结束进程的方法和2种异常终止的方法: 1. 正常结束: a. 在main函数中调用return ...

  5. Linux进不了进程,既然在Linux中程序不是进程,那么到底什么才算是进程呢?

    C语言程序员编写的代码可以编译为程序,程序通常存放在磁盘等存储介质中.在 Linux 中,处于运行期的程序被称作"进程". 处于运行期的程序被称作"进程" 进程 ...

  6. linux mysql 进程查看工具_linux查看正在运行的进程(如何在Linux中查看所有正在运行的进程)...

    如何在Linux中查看所有正在运行的进程 名称:ps 使用权限:所有使用者 使用方式:ps [options] [--help] 说明:显示瞬间行程 (process) 的动态 参数:ps的参数非常多 ...

  7. 【Linux操作系统基础】第六章 Linux中的进程管理

    一.进程及其状态 程序是静态的代码文件,没有生命周期.进程是指程序运行时的形态,是程序的一个副本,进程有生命周期(准备期,运行期,终止期) 进程是资源调用的最小单位,系统中的资源在同一时间只能被同一个 ...

  8. linux查询某域线程是否满了,Linux多线程编程的时候怎么查看一个进程中的某个线程是否存活...

    pthread_kill: 别被名字吓到,pthread_kill可不是kill,而是向线程发送signal.还记得signal吗,大部分signal的默认动作是终止进程的运行,所以,我们才要用sig ...

  9. linux系统怎么结束程序,如何在 Linux 系统中结束进程或是中止程序

    如何在 Linux 系统中结束结束进程或是中止程序 进程出错的时候,您可能会想要中止或是中断这个进程.本文,我们将在命令行和图形界面中探索进程或是应用程序的中断,这里我们使用 gedit 作为样例程序 ...

最新文章

  1. 如何加入家庭组计算机打印机,如何使用利用win7家庭组打印机
  2. 别总埋汰写代码,停下总结一下吧
  3. Libsvm的一些说明帮助吧
  4. CSS页面重构“鑫三无准则”之“无图片”准则——张鑫旭
  5. phpstudy运行PHP项目出现404怎么办?
  6. 如何将一个完整项目推到码云_怎么将本地项目放到码云(gitee)上面?图文详解
  7. java按年月季度统计折线图_拆线图按年、按月,按天统计,前端传时间只要起始时间与结束时间...
  8. 史上最强Dubbo面试26题和答案:核心组件+服务治理+架构设计等
  9. hdu1426 Sudoku Killer dfs
  10. 新塘单片机烧写器_新唐MCU常用的工具软件
  11. FFMPEG 编解码失败 non-existing PPS 0 referenced
  12. 为什么计算机打不开优盘,U盘打不开,且8G的U盘只报64M,为什么?
  13. 如何从程序员升级到架构师?
  14. 英文标点符号unicode
  15. 爬虫实战 | 爬取东方财富网股票数据
  16. 计算机三级嵌入式工程师,怎样通过计算机三级嵌入式,如何成为嵌入式工程师——第一章嵌入式系统概论
  17. 【算法记录】梅式砝码问题
  18. Maya动画——使用诺亦腾惯性动捕设备进行动作捕捉的方法
  19. AC自动机笔记与例题整理
  20. 如何科学地进行A_B实验

热门文章

  1. 怎样在Linux系统中编译,Linux操作系统如何编译程序?
  2. 北京内推 | 微软亚洲研究院MSRA STCA招聘多模态算法实习生
  3. RUN++ | 对比学习加持,多轮对话改写新SOTA!
  4. 预训练图像处理Transformer:刷榜多项底层视觉任务
  5. 基于多域连接卷积神经网络的精神分裂症脑功能网络分类
  6. AIProCon在线大会笔记之张钹院士:探索第三代人工智能,需要勇闯无人区的人才!
  7. MySQL学习第三章练习题
  8. 如何自动填充网页表单_iCab for Mac(web网页浏览器)
  9. 十大经典排序算法总结(够兄弟们喝一壶的)
  10. 数据结构和算法之稀疏数组