zoukankan      html  css  js  c++  java
  • Linux下的进程与线程(二)—— 信号

    Linux进程之间的通信:

    本文主要讨论信号问题。

    在Linux下的进程与线程(一)中提到,调度器可以用中断的方式调度进程

    然而,进程是怎么知道自己需要被调度了呢?是内核通过向进程发送信号,进程才得以知道的。

    Linux系统的进程之间是通过信号来通信的。

    程序员在Shell上显式地发送信号使用的是kill命令,原型如下:

    kill -sigid [-]pid

    其中, sigid指示的是信号的id,pid前若有-,则pid代表的为进程组id,否则pid代表的为进程id

    kill函数也有相同的作用,原型如下:

    int kill(pid_t pid, int sig);

    一个使用kill命令的典型例子如下:

    我们在Linux的Shell上运行一个前台作业的时候,Shell会fork一个新的进程A,然后在这个新的进程中运行我们的作业。该前台作业在运行时也可能会fork子进程a,子进程b。

    当我们按下Ctrl+C,Shell会收到一个SIGINT信号,然后Shell进程会转发这个信号到A,然后A再将这个信号转发到子进程a,子进程b。

    通过这种转发的方式,实现信号传递。

    下图摘自CS:APP(图8-27),在本书的举例中,前台作业运行的是 ls | sort,图示一目了然:

    值得一提的是,当父进程创建子进程之后,父子进程的进程组ID(pgid)是相同的。

    信号的等待与阻塞

    如果一个进程正在处理类型为k的信号,那么此时当另一个k信号到的时候,进程的pending位向量(待处理信号集)的第k位会被设置。但这个刚到的k信号不会被立即处理,直到handler程序返回。

    如果此时来了一个k信号,那么由于此前pending位向量已被设置,所以这个信号会被丢弃

    一旦进程接收了信号k,那么内核就会清除pending的第k位。

    blocked位向量(被阻塞信号集)维护着进程阻塞的信号,在这里设置的信号不会被进程接收处理。

    所以我们知道,pending & ~blocked 的结果指示了进程将要去接收处理的信号集。

    信号中断慢速系统调用

    诸如read,wait,accept之类的慢速系统调用会阻塞进程,在特定的Solaris系统上,当被阻塞的进程被信号中断之后,将不会再返回。而是给用户一个错误条件,并对errno进行设置。

    在Linux系统上,会自动重启被中断的系统调用.

    为了使得编写的代码在Linux和Solaris系统上都能运行,需编写可移植性代码.

    接收信号

    进程接收每一个信号之后都有默认的行为,比如接收SIGKILL信号后,进程被终止。

    可以设置signal函数,来修改部分信号的默认行为:

    sighandler_t signal(int signum, sighandler_t handler)

    其中,signum为要捕获的信号,handler为捕获信号后要执行的函数名称。

  • 相关阅读:
    126.输入输出深入以及小结
    125.C++输入小结
    124.C++输出小结
    123.static静态函数与类模板
    123.static静态函数和函数模板
    122.模板与友元
    121.类模板当做参数
    120.嵌套类模板
    119.类模板的默认参数规则
    正睿 2019 省选附加赛 Day1 T1 考考试
  • 原文地址:https://www.cnblogs.com/geeklove01/p/7932835.html
Copyright © 2011-2022 走看看