专栏首页三丰SanFengLinux进程间通信(三) - 信号

Linux进程间通信(三) - 信号

什么是信号

软中断信号(signal,又简称为信号)用来通知进程发生了异步事件。在软件层次上是对中断机制的一种模拟,在原理上,一个进程收到一个信号与处理器收到一个中断请求可以说是一样的。信号是进程间通信机制中唯一的异步通信机制,一个进程不必通过任何操作来等待信号的到达,事实上,进程也不知道信号到底什么时候到达。进程之间可以互相通过系统调用kill发送软中断信号。内核也可以因为内部事件而给进程发送信号,通知进程发生了某个事件。信号机制除了基本通知功能外,还可以传递附加信息。

收到信号的进程对各种信号有不同的处理方法。处理方法可以分为三类:

Ø 类似中断的处理程序,对于需要处理的信号,进程可以指定处理函数,由该函数来处理。

Ø 忽略某个信号(SIG_IGN),对该信号不做任何处理,就象未发生过一样。

Ø 对该信号的处理保留系统的默认值(SIG_DFL),这种缺省操作,对大部分的信号的缺省操作是使得进程终止。进程通过系统调用signal来指定进程对某个信号的处理行为。

查看目前支持的信号值

[root@bogon demo]# kill -l

1) SIGHUP 2) SIGINT 3) SIGQUIT 4) SIGILL 5) SIGTRAP

6) SIGABRT 7) SIGBUS 8) SIGFPE 9) SIGKILL 10) SIGUSR1

11) SIGSEGV 12) SIGUSR2 13) SIGPIPE 14) SIGALRM 15) SIGTERM

16) SIGSTKFLT 17) SIGCHLD 18) SIGCONT 19) SIGSTOP 20) SIGTSTP

21) SIGTTIN 22) SIGTTOU 23) SIGURG 24) SIGXCPU 25) SIGXFSZ

26) SIGVTALRM 27) SIGPROF 28) SIGWINCH 29) SIGIO 30) SIGPWR

31) SIGSYS 34) SIGRTMIN 35) SIGRTMIN+1 36) SIGRTMIN+2 37) SIGRTMIN+3

38) SIGRTMIN+4 39) SIGRTMIN+5 40) SIGRTMIN+6 41) SIGRTMIN+7 42) SIGRTMIN+8

43) SIGRTMIN+9 44) SIGRTMIN+10 45) SIGRTMIN+11 46) SIGRTMIN+12 47) SIGRTMIN+13

48) SIGRTMIN+14 49) SIGRTMIN+15 50) SIGRTMAX-14 51) SIGRTMAX-13 52) SIGRTMAX-12

53) SIGRTMAX-11 54) SIGRTMAX-10 55) SIGRTMAX-9 56) SIGRTMAX-8 57) SIGRTMAX-7

58) SIGRTMAX-6 59) SIGRTMAX-5 60) SIGRTMAX-4 61) SIGRTMAX-3 62) SIGRTMAX-2

63) SIGRTMAX-1 64) SIGRTMAX

信号的分类

可以从两个不同的分类角度对信号进行分类:

Ø 可靠性方面:可靠信号与不可靠信号;

Ø 与时间的关系上:实时信号与非实时信号。

可靠信号与不可靠信号

Linux信号机制基本上是从Unix系统中继承过来的。早期Unix系统中的信号机制比较简单和原始,信号值小于SIGRTMIN的信号都是不可靠信号。这就是"不可靠信号"的来源。它的主要问题是信号可能丢失。

随着时间的发展,实践证明了有必要对信号的原始机制加以改进和扩充。由于原来定义的信号已有许多应用,不好再做改动,最终只好又新增加了一些信号,并在一开始就把它们定义为可靠信号,这些信号支持排队,不会丢失。

信号值位于SIGRTMIN和SIGRTMAX之间的信号都是可靠信号,可靠信号克服了信号可能丢失的问题。Linux在支持新版本的信号安装函数sigation()以及信号发送函数sigqueue()的同时,仍然支持早期的signal()信号安装函数,支持信号发送函数kill()。

信号的可靠与不可靠只与信号值有关,与信号的发送及安装函数无关。目前linux中的signal()是通过sigation()函数实现的,因此,即使通过signal()安装的信号,在信号处理函数的结尾也不必再调用一次信号安装函数。同时,由signal()安装的实时信号支持排队,同样不会丢失。

对于目前linux的两个信号安装函数:signal()及sigaction()来说,它们都不能把SIGRTMIN以前的信号变成可靠信号(都不支持排队,仍有可能丢失,仍然是不可靠信号),而且对SIGRTMIN以后的信号都支持排队。这两个函数的最大区别在于,经过sigaction安装的信号都能传递信息给信号处理函数,而经过signal安装的信号不能向信号处理函数传递信息。对于信号发送函数来说也是一样的。

实时信号与非实时信号

早期Unix系统只定义了32种信号,前32种信号已经有了预定义值,每个信号有了确定的用途及含义,并且每种信号都有各自的缺省动作。如按键盘的CTRL ^C时,会产生SIGINT信号,对该信号的默认反应就是进程终止。后32个信号表示实时信号,等同于前面阐述的可靠信号。这保证了发送的多个实时信号都被接收。

非实时信号都不支持排队,都是不可靠信号;实时信号都支持排队,都是可靠信号。

信号相关函数说明

#include <signal.h>

void (*signal(int signum, void (*handler))(int)))(int);

如果该函数原型不容易理解的话,可以参考下面的分解方式来理解:

typedef void (*sighandler_t)(int);

sighandler_t signal(int signum, sighandler_t handler));

第一个参数指定信号的值,第二个参数指定针对前面信号值的处理,可以忽略该信号(参数设为SIG_IGN);可以采用系统默认方式处理信号(参数设为SIG_DFL);也可以自己实现处理方式(参数指定一个函数地址)。

如果signal()调用成功,返回最后一次为安装信号signum而调用signal()时的handler值;失败则返回SIG_ERR。

传递给信号处理例程的整数参数是信号值,这样可以使得一个信号处理例程处理多个信号。

信号案例说明

案例设计

Ø 进程收到SIGHUP,SIGINT,SIGQUIT,提示收到对应的信号,不做任何处理

Ø 进程中有个计数器,当用户发出SIGUSR1,SIGUSR2时,打印出这个计数器的值

Ø 对信号9(SIGKILL)和信号11(SIGSEGV)分别做忽略和默认处理

代码说明:

#include <unistd.h>  
#include <stdlib.h>  
#include <stdio.h>  
#include <fcntl.h>  
#include <sys/types.h>  
#include <sys/stat.h>  
#include <limits.h>  
#include <string.h> 
#include <signal.h>

int count = 1;
void deal_sig(int signum)
{
    switch(signum)
    {
    case 1: // SIGHUP
        printf("signal SIGHUP cached\n");
        break;
    case 2: // SIGINT
        printf("signal SIGINT cached\n");
        break;
    case 3: // SIGQUIT
        printf("signal SIGQUIT cached\n");
        break;
    case 10: // SIGUSR1
        printf("signal SIGUSR1 cached, count = %d\n", count);
        break;
    case 12: // SIGUSR2
        printf("signal SIGUSR2 cached, count = %d\n", count);
        break;
    }
    return;
}
  
int main(int argc, char** argv)  
{  
   signal(SIGHUP, deal_sig);
   signal(SIGINT, deal_sig);
   signal(SIGQUIT, deal_sig);
   signal(SIGUSR1, deal_sig);
   signal(SIGUSR2, deal_sig);
   signal(SIGKILL, SIG_IGN);
   signal(SIGSEGV, SIG_DFL);
   while(1)
   {
       count++;
       sleep(1);
   }
   return 0;
}

结果说明:

tty1:

[root@bogon ipc]# g++ -g -o ipc_signal ipc_signal.cpp

[root@bogon ipc]# ./ipc_signal

^Csignal SIGINT cached // 这里按下 CTRL + C

signal SIGHUP cached

signal SIGINT cached

signal SIGQUIT cached

signal SIGUSR1 cached, count = 73

signal SIGUSR2 cached, count = 79

Killed // 这里发现SIGKILL信号是忽略不掉的,进程还是退出了

[root@bogon ipc]# ./ipc_signal

Segmentation fault (core dumped) // 收到段错误信号,产生core并退出

tty2:

[root@bogon ipc]# ps axu|grep ipc_signal

root 20380 0.0 0.0 11740 828 pts/1 S+ 00:50 0:00 ./ipc_signal

root 20389 0.0 0.0 103252 812 pts/2 S+ 00:50 0:00 grep ipc_signal

[root@bogon ipc]# kill -HUP 20380

[root@bogon ipc]# kill -INT 20380

[root@bogon ipc]# kill -QUIT 20380

[root@bogon ipc]# kill -USR1 20380

[root@bogon ipc]# kill -USR2 20380

[root@bogon ipc]# kill -KILL 20380

[root@bogon ipc]# ps axu|grep ipc_signal

root 20445 0.0 0.0 11736 780 pts/1 S+ 00:52 0:00 ./ipc_signal

root 20448 0.0 0.0 103252 812 pts/2 S+ 00:53 0:00 grep ipc_signal

[root@bogon ipc]# kill -SEGV 20445

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

我来说两句

0 条评论
登录 后参与评论

相关文章

  • Linux删除乱码文件的方法

    当文件名为乱码的时候,无法通过键盘输入文件名,所以在终端下就不能直接利用rm,mv等命令管理文件了。 我们可以通过以下几种方法删除linux下的乱码文件。(文件...

    三丰SanFeng
  • Linux进程间通信(一) - 管道

    管道(pipe) 普通的Linux shell都允许重定向,而重定向使用的就是管道。 例如:ps | grep vsftpd .管道是单向的、先进先出的、无结构...

    三丰SanFeng
  • zookeeper监控告警

    一、ZooKeeper简介 ZooKeeper作为分布式系统中重要的组件,目前在业界使用越来越广泛,ZooKeeper的使用场景非常多,以下是几种典型的应用场景...

    三丰SanFeng
  • linux系统编程之信号(一):信号基本概述

    一、为了理解信号,先从我们最熟悉的场景说起: 1. 用户输入命令,在Shell下启动一个前台进程。 2. 用户按下Ctrl-C,这个键盘输入产生一个硬件中断...

    s1mba
  • Linux环境下 LVM 逻辑卷的建立、扩容和减容操作

    LVM是逻辑盘卷管理(Logical Volume Manager)的简称,它是Linux环境下对磁盘分区进行管理的一种机制,LVM是建立在硬盘和分区之上的一个...

    小小科
  • 基于模型的系统工程——自动驾驶汽车(20180928更新)

    原文链接:http://intercax.com/2018/01/11/model-based-systems-engineering-autonomous-v...

    用户6288414
  • Java中Collections.sort()方法的演变结果分析源码分析关于Java8中Collections.sort方法的修改

    JavaEdge
  • 面对各种数据怎么处理 : 特征工程之特征表达

    地址:https://www.cnblogs.com/pinard/p/9032759.html

    机器学习算法工程师
  • JVM系列第15讲:JDK性能监控命令

    jps 命令可以列出所有的 Java 进程。如果 jps 不加任何参数,可以列出 Java 程序的进程 ID 以及 Main 函数短名称,如下所示。

    陈树义
  • 圆的反演变换

    挺神奇的东西,网上没有多少资料,我也不是太懂,代码什么的都没写过,那就抄一下百度百科吧

    attack

扫码关注云+社区

领取腾讯云代金券