zoukankan      html  css  js  c++  java
  • Linux进程间通信(四)信号通信之信号发送捕捉kill()、raise()、alarm()、pause()及其基础实验

    信号概述

       ●  信号是在软件层次上对中断机制的一种模拟。在原理上,一个进程收到一个信号与处理器收到一个中断请求可以说是一样的。

       ●  信号是异步的,一个进程不必通过任何操作来等待信号的到达,事实上进程也不知道信号到底什么时候到达。

       ●  信号可以直接进行用户空间进程和内核进程之间的交互,内核进程也可以利用它来通知用户空间进程发生了哪些系统事件。它可以在任何时候发给某一个进程,而无需知道该进程的状态。如果该信号当前并未处于执行态(Running),则该信号由内核保存起来,直到该进程恢复执行再传递给它为止。如果一个信号被进程设置为阻塞,则该信号的传递被延迟,直到其阻塞被取消时才被传递给进程。

       ●  信号是进程间通信机制中唯一的异步通信机制,可以看作是异步通知,通知接收信号的进程有哪些事件发生了。信号机制除了基本通知外,还可以传递附加信息。

    信号来源

         信号事件发生的来源有两种:

         ① 硬件来源。如我们按下了键盘上的按钮 或者出现其他硬件故障;

         ② 软件来源。最常用发送信号的系统函数有kill()、raise()、alarm()、setitimer()和sigqueue()等,软件来源还包括一些非法运算等操作。

    进程响应信号的方式

        ① 忽略信号。忽略信号即对信号不做处理,其中,有两个信号不能忽略:SIGKILL和SIGSTOP。

        ② 捕捉信号。定义信号处理函数,当信号发生时,执行响应的处理函数。

        ③ 执行默认操作。Linux对每种信号都规定了默认操作,如下表所示:

       


    信号的生命周期

         一个完整的信号生命周期可以分为3个重要阶段,这3个阶段由4个重要事件来刻画的;信号产生、信号在进程中注册、信号在进程中注销、执行信号处理函数。这里信号的产生、注册、注销等是指信号的内部实现机制,而不是信号的函数实现(不受我们的掌控)。因此信号注册与否与后面讲到的发送信号函数(如 kill()等)及信号安装函数(如 signal()等)无关,只与信号值有关。

       相邻两个事件的时间间隔构成信号生命周期的一个阶段,如下图1.注意这里的信号处理有多种方式,一般是由内核完成的,当然也可以由用户进程来完成。

       

        信号的处理包括信号的发送、捕捉和处理,它们有各自相对应的常见函数:

        ●  发生信号的函数: kill()、raise()。 

        ●  捕捉信号的函数: alarm()、pause()。

        ●  处理信号的函数: signal()、sigaction()。

      本节主要讲信号的发送与捕捉,下一节再讲处理

    信号发送函数 kill()和raise()

    函数说明

       kill()函数同咱们的kill系统命令一样(但不能误以为kill()就是kill哈),可以发送信号给进程或进程组(实际上,kill系统命令只是kill()函数的一个用户接口)。这里需要注意的是,kill()函数不仅可以终止进程(实际上是通过发出SIGKILL信号终止),也可以向进程发送其他信号。

       与kill()函数不同的是,raise()函数允许进程向自身发送信号。

    函数格式

       下表分别列出了kill()和raise()的格式

          

          


    基础实验

       本实验首先使用 fork()创建了一个子进程,接着为了保证子进程不在父进程调用kill()之前退出,在子进程中使用raise()函数向自身发送 SIGSTOP信号,使子进程暂停。接下来在父进程中调用kill()向子进程发送信号,在该实验中使用的是SIGKILL。实验代码如下:

       kill_raise.c文件点此下载

          

       编译后执行的效果如下图

       

       你瞧瞧,多狠啊,都不让子进程输出第22行的话,直接啪的就给人拍那里了。

       另外,建议你去掉27行的代码再执行一遍试一试看看有什么不同。

    信号捕捉函数: alarm()、pause()

    函数说明

        alarm()也称为闹钟函数,它可以在进程中设置一个定时器,当定时器指定的时间到时,它就向进程发送SIGALARM信号。要注意的是,一个进程只能有一个闹钟时间,如果在调用alarm()之前已设置过闹钟时间,则任何以前的闹钟时间都被新值所代替。

       pause()函数用于将调用进程挂起直至捕捉到信号为止。这个函数很常用,通常可以用于判断信号是否已到。

    函数格式

       

        



    基础实验

        本实验实际上是完成了一个简单的sleep()函数的功能,程序如下图

         

       编译执行后,结果如下图

       

      可以看到12行的语句根本就没执行,其实想想程序的执行流程就很清除,首先程序定时,执行到11行pause();时进程会被挂起,当计时到,发出信号SIGALARM,这时pause()捕捉到信号,进程直接被终止。

        现在屏蔽掉11行,如下

        

       再次编译执行,结果如下图

       

      下一节学习一下信号的处理,如需转载,请注明出处:http://blog.csdn.net/mybelief321/article/details/9078193

      最后,顺祝大家端午节快乐!!也顺祝今年的金九银十顺利!

  • 相关阅读:
    路径专题
    java.lang.IllegalArgumentException: Result Maps collection does not contain value for java.lang.Integer
    DER input, Integer tag error的异常处理
    myeclipse,eclipse控制台输出乱码问题
    大话设计模式之简单工厂模式
    Maven安装与配置
    IDEA: 遇到问题Error during artifact deployment. See server log for details.详解
    IntelliJ IDEA 中 右键新建时,选项没有Java class的解决方法和具体解释
    微信内置浏览器和小程序的 User Agent 区别及判断方法
    WAMP 403 Forbidden禁止访问
  • 原文地址:https://www.cnblogs.com/dyllove98/p/3132798.html
Copyright © 2011-2022 走看看