二 Linux进程间通信

信号信号的概念信号是Linux进程间通信的最古老的一种方式 。信号是软件中断 , 是一种异步通信的方式 。信号可以导致一个正在运行的进程被另一个正在运行的异步进程中断,转而处理某个突发事件 。
一旦产生信号,就要执行信号处理函数 , 处理完信号处理函数,再回来执行主函数,这就是中断 。
一个完整的信号周期包括三个部分:信号的产生,信号在进程中的注册 , 信号的进程中的销毁,执行信号处理函数 。

二 Linux进程间通信

文章插图
注意:这里信号的产生、注册、注销都是信号的内部机制,而不是信号的函数实现 。
查看信号可以通过kill -l命令查看系统定义的信号列表:
二 Linux进程间通信

文章插图
可以看到,不存在编号为0的信号 。其中1-31号信号成为常规信号(也叫普通信号和标准信号) , 34-64称为实时信号,驱动编程与硬件相关 。名字上差别不大,而前32个名字各不相同 。
如果你想了解某个信号的产生条件和默认处理动作,可以通过指令man signal_id signal
例如: man2 signal 就是查看二号信号的作用
信号四要素
  • 编号
  • 名称
  • 事件
  • 默认处理动作

二 Linux进程间通信

文章插图
可以看到有一些信号具有三个“value”,第一个值通常对alpha和sparc架构有用 , 中间值针对x86和arm架构,最后一个应用于mips架构 。
不同的操作系统定义了不同的系统信号,这里我们之研究linux系统中的信号 。
Action为默认动作:
  • Term:终止进程
  • Ign:忽略信号
  • Core:终止进程 , 生成Core文件 。(检查死亡原因,用于gdb调试)
  • Stop:终止(暂停)进程
  • Cont:继续执行进程
  • 强调 9)SIGKILL和19)SIGSTOP信号,不允许忽略和捕捉 , 只能执行默认的动作,甚至不能将其设为阻塞
信号的产生通过按键产生当用户按下某些终端按键的时候,将产生信号
  • 按键Ctrl C可以发送2号信号(SIG_INT),默认处理动作是终止进程
  • 按键按下Ctrl \,发送3号信号(SIG_QUIT) , 默认处理动作是终止进程并且Core Dump
  • 按键按下Ctrl z查安生终端信号SIGSTOP,默认动作是暂停进程的执行
Core Dump是什么?
当一个进程要异常终止时,可以选择把进程的用户空间内存数据全部保存到磁盘上,文件名通常是core,这叫做Core Dump 。我们可以通过使用gdb调试查看core文件查看进程退出的原因,这也叫事后调试 。
通过系统调用下面介绍三个系统函数
(1)kill函数
#include<sys/types.h>#include<signal.h>int kill(pid_t pid,int sig);功能:给指定进程发送指定信号(不一定杀死)参数:pid:取值有4种情况:pid > 0:将信号传送给进程ID为pid的进程 。pid = 0:将信号传送给当前进程所在进程组中的所有进程 。pid = -1:将信号传送给系统内所有的进程 。pid < -1:将信号传给指定进程组的所有进程 。这个进程组号等于pid的绝对值 。sig:信号的编号,这里可以填数字编号,也可以填信号的宏定义,可以通过命令kill -l进行相应查看 。不准荐直接使数字,应使用宏名 , 因为不同操作系统信号编号可能不同 , 但名称一致 。返回值.成功:0失败:-1
  • super用户(root)可以发送信号给任意用户,普通用户是不能向系统用户发送信号的 。
  • 普通用户不能向其他普通用户发送信号 , 终止其进程 , 只能向自己创建的进程发送信号 。
代码示例:
#include<stdio.h>#include<signal.h>#include<sys/types.h>#include<unistd.h> int main() {pid_t pid;//创建一个子进程pid = fork();{printf("child process do work.....\n");sleep(1);}exit(0);//子进程退出}else{//父进程sleep(3);printf("子进程不听话了,该退出了....\n");kill(pid,15);printf("父进程该结束了 , 已经完成了它的使命\n");}return 0; }运行结果如下:
二 Linux进程间通信

文章插图
(2)raise函数
#include<signal.h>int raise(int sig);功能:给当前进程发送指定信号(自己给自己发),等价于kill(getpid(),sig)参数: sig:信号编号返回值:成功:0失败:非0值

推荐阅读