Linux進(jìn)程通信 | 信號
一、什么是信號?
信號就像是一個突然的電話鈴聲,它會打斷正在進(jìn)行的程序并引起其注意。
在Linux系統(tǒng)中,信號是一種軟件中斷,它通常是異步發(fā)生的,可以用來通知進(jìn)程某個事件已經(jīng)發(fā)生。。每個信號都有一個唯一的編號,編號從1開始。進(jìn)程可以通過注冊信號處理函數(shù)來處理信號。
二、信號的分類
Linux系統(tǒng)中的信號有兩類:標(biāo)準(zhǔn)信號和實(shí)時信號。
-
標(biāo)準(zhǔn)信號是傳統(tǒng)Unix系統(tǒng)中的信號,編號范圍從1到31。
-
實(shí)時信號是Linux獨(dú)有的信號,編號范圍從32到64。
三、信號的使用
1、注冊信號處理函數(shù)
在C語言中,可以使用signal函數(shù)來注冊信號處理函數(shù)。signal函數(shù)原型如下:
void (*signal(int signum, void (*handler)(int)))(int);
其中,signum參數(shù)表示要注冊的信號編號,handler參數(shù)表示信號處理函數(shù)。signal函數(shù)會返回上一次注冊的信號處理函數(shù)的地址。
下面是一個簡單的例子,注冊SIGINT信號的處理函數(shù):
#include <stdio.h>
#include <signal.h>
#include <stdlib.h>
void sigint_handler(int signo)
{
printf("Received SIGINT signal!\n");
exit(0);
}
int main()
{
if (signal(SIGINT, sigint_handler) == SIG_ERR) {
perror("signal");
exit(1);
}
while (1) {
printf("Hello World!\n");
sleep(1);
}
return 0;
}
在上面的例子中,我們首先定義了一個名為sigint_handler的函數(shù),用于處理SIGINT信號。
在main函數(shù)中,我們使用signal函數(shù)注冊了SIGINT信號的處理函數(shù)。如果signal函數(shù)返回的值是SIG_ERR,表示注冊信號處理函數(shù)失敗。
在循環(huán)中,我們只是簡單地輸出Hello World!字符串,并使用sleep函數(shù)暫停1秒鐘,以便觀察信號處理過程。
- 編譯并運(yùn)行,打印如下
[wayne@wayne:~]./signal
Hello World!
Hello World!
Hello World!
2、發(fā)送信號
2.1 kill函數(shù)
在Linux系統(tǒng)中,可以使用kill函數(shù)向進(jìn)程發(fā)送信號。kill函數(shù)原型如下:
int kill(pid_t pid, int sig);
其中,pid參數(shù)表示進(jìn)程的PID號,sig參數(shù)表示要發(fā)送的信號編號。如果pid參數(shù)的值是0,表示將信號發(fā)送給與當(dāng)前進(jìn)程屬于同一個進(jìn)程組的所有進(jìn)程。
下面是一個例子,向指定進(jìn)程發(fā)送SIGINT信號:
#include <stdio.h>
#include <signal.h>
#include <stdlib.h>
#include <unistd.h>
int main(int argc, char **argv)
{
if (argc < 2) {
fprintf(stderr, "Usage: %s <pid>\n", argv[0]);
exit(1);
}
pid_t pid = atoi(argv[1]);
if (kill(pid, SIGINT) == -1) {
perror("kill");
exit(1);
}
return 0;
}
在上面的例子中,我們首先檢查命令行參數(shù),如果參數(shù)不足,就打印使用說明并退出程序。
然后我們將命令行參數(shù)轉(zhuǎn)換為進(jìn)程PID號,并使用kill函數(shù)向該進(jìn)程發(fā)送SIGINT信號。如果kill函數(shù)返回-1,表示發(fā)送信號失敗。
- 編譯并運(yùn)行,打印如下
[wayne@wayne:~] ps aux | grep signal
wayne 5902 0.0 0.0 2028 280 pts/25 S+ 19:04 0:00 ./signal
wayne 5904 0.0 0.0 6108 852 pts/24 S+ 19:04 0:00 grep --color=auto signal
[wayne@wayne:~] ./killsignal 5902
// 此時上面運(yùn)行的signal進(jìn)程會收到信號,打印如下信息
Received SIGINT signal!
2.2 kill命令
我們也可以在shell中,用kill命令向進(jìn)程發(fā)送信號,kill命令的語法如下:
kill [options] <pid>
其中,pid表示要發(fā)送信號的進(jìn)程PID號。options是一些可選參數(shù),例如,可以使用-9參數(shù)發(fā)送SIGKILL信號。
我們可以打開一個新的終端窗口,使用ps命令查看本文介紹的示例程序的PID號,然后使用kill命令向該進(jìn)程發(fā)送SIGINT信號,示例如下:
$ ps aux | grep signal
wayne 5902 0.0 0.0 2028 280 pts/25 S+ 19:04 0:00 ./signal
wayne 5904 0.0 0.0 6108 852 pts/24 S+ 19:04 0:00 grep --color=auto signal
$ kill -2 5902
這里我們使用ps命令查找名為signal的進(jìn)程的PID號為5902,然后使用kill命令向該進(jìn)程發(fā)送SIGINT信號(信號編號為2)。在執(zhí)行kill命令之后,我們可以看到示例程序輸出了"Received SIGINT signal"這一行信息,說明信號處理函數(shù)已經(jīng)被正確調(diào)用了。
四、常用信號
Linux系統(tǒng)中常用的信號有很多,下面列出一些常用的信號及其含義:
| 信號編號 | 信號名稱 | 含義 |
|---|---|---|
| 1 | SIGHUP | 終端掛起或者控制進(jìn)程結(jié)束 |
| 2 | SIGINT | 中斷信號,通常是CTRL-C |
| 3 | SIGQUIT | 終止信號,通常是CTRL-\ |
| 9 | SIGKILL | 強(qiáng)制終止進(jìn)程 |
| 11 | SIGSEGV | 段錯誤 |
| 15 | SIGTERM | 終止信號,通常是kill命令發(fā)送的信號 |
| 18 | SIGCONT | 繼續(xù)執(zhí)行被暫停的進(jìn)程 |
| 19 | SIGSTOP | 暫停進(jìn)程 |
| 20 | SIGTSTP | 終端掛起或者CTRL-Z |
五、小結(jié)
總的來說,Linux 信號是一種用于通知進(jìn)程發(fā)生某個事件或錯誤的機(jī)制,可以用于處理異常情況、進(jìn)程間通信等多種場景。
以上,如果覺得對你有幫助,點(diǎn)個贊再走吧,這樣@知微之見也有更新下去的動力!
也歡迎私信我,一起交流!

浙公網(wǎng)安備 33010602011771號