一、什麼是信號? 信號就像是一個突然的電話鈴聲,它會打斷正在進行的程式並引起其註意。 在Linux系統中,信號是一種軟體中斷,它通常是非同步發生的,可以用來通知進程某個事件已經發生。。每個信號都有一個唯一的編號,編號從1開始。進程可以通過註冊信號處理函數來處理信號。 二、信號的分類 Linux系統中的 ...
一、什麼是信號?
信號就像是一個突然的電話鈴聲,它會打斷正在進行的程式並引起其註意。
在Linux系統中,信號是一種軟體中斷,它通常是非同步發生的,可以用來通知進程某個事件已經發生。。每個信號都有一個唯一的編號,編號從1開始。進程可以通過註冊信號處理函數來處理信號。
二、信號的分類
Linux系統中的信號有兩類:標準信號和實時信號。
-
標準信號是傳統Unix系統中的信號,編號範圍從1到31。
-
實時信號是Linux獨有的信號,編號範圍從32到64。
三、信號的使用
1、註冊信號處理函數
在C語言中,可以使用signal函數來註冊信號處理函數。signal函數原型如下:
void (*signal(int signum, void (*handler)(int)))(int);
其中,signum參數表示要註冊的信號編號,handler參數表示信號處理函數。signal函數會返回上一次註冊的信號處理函數的地址。
下麵是一個簡單的例子,註冊SIGINT信號的處理函數:
#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的函數,用於處理SIGINT信號。
在main函數中,我們使用signal函數註冊了SIGINT信號的處理函數。如果signal函數返回的值是SIG_ERR,表示註冊信號處理函數失敗。
在迴圈中,我們只是簡單地輸出Hello World!字元串,並使用sleep函數暫停1秒鐘,以便觀察信號處理過程。
- 編譯並運行,列印如下
[wayne@wayne:~]./signal
Hello World!
Hello World!
Hello World!
2、發送信號
2.1 kill函數
在Linux系統中,可以使用kill函數向進程發送信號。kill函數原型如下:
int kill(pid_t pid, int sig);
其中,pid參數表示進程的PID號,sig參數表示要發送的信號編號。如果pid參數的值是0,表示將信號發送給與當前進程屬於同一個進程組的所有進程。
下麵是一個例子,向指定進程發送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;
}
在上面的例子中,我們首先檢查命令行參數,如果參數不足,就列印使用說明並退出程式。
然後我們將命令行參數轉換為進程PID號,並使用kill函數向該進程發送SIGINT信號。如果kill函數返回-1,表示發送信號失敗。
- 編譯並運行,列印如下
[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
// 此時上面運行的signal進程會收到信號,列印如下信息
Received SIGINT signal!
2.2 kill命令
我們也可以在shell中,用kill命令向進程發送信號,kill命令的語法如下:
kill [options] <pid>
其中,pid表示要發送信號的進程PID號。options是一些可選參數,例如,可以使用-9參數發送SIGKILL信號。
我們可以打開一個新的終端視窗,使用ps命令查看本文介紹的示常式序的PID號,然後使用kill命令向該進程發送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的進程的PID號為5902,然後使用kill命令向該進程發送SIGINT信號(信號編號為2)。在執行kill命令之後,我們可以看到示常式序輸出了"Received SIGINT signal"這一行信息,說明信號處理函數已經被正確調用了。
四、常用信號
Linux系統中常用的信號有很多,下麵列出一些常用的信號及其含義:
信號編號 | 信號名稱 | 含義 |
---|---|---|
1 | SIGHUP | 終端掛起或者控制進程結束 |
2 | SIGINT | 中斷信號,通常是CTRL-C |
3 | SIGQUIT | 終止信號,通常是CTRL-\ |
9 | SIGKILL | 強制終止進程 |
11 | SIGSEGV | 段錯誤 |
15 | SIGTERM | 終止信號,通常是kill命令發送的信號 |
18 | SIGCONT | 繼續執行被暫停的進程 |
19 | SIGSTOP | 暫停進程 |
20 | SIGTSTP | 終端掛起或者CTRL-Z |
五、小結
總的來說,Linux 信號是一種用於通知進程發生某個事件或錯誤的機制,可以用於處理異常情況、進程間通信等多種場景。
以上,如果覺得對你有幫助,點個贊再走吧,這樣@知微之見也有更新下去的動力!
也歡迎私信我,一起交流!