二 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失?。悍?值

推薦閱讀