一遂蛀、什么是信號(hào)真椿?
信號(hào)就像是一個(gè)突然的電話鈴聲鹃答,它會(huì)打斷正在進(jìn)行的程序并引起其注意。
在Linux系統(tǒng)中突硝,信號(hào)是一種軟件中斷测摔,它通常是異步發(fā)生的,可以用來(lái)通知進(jìn)程某個(gè)事件已經(jīng)發(fā)生解恰。锋八。每個(gè)信號(hào)都有一個(gè)唯一的編號(hào),編號(hào)從1開始护盈。進(jìn)程可以通過(guò)注冊(cè)信號(hào)處理函數(shù)來(lái)處理信號(hào)查库。
二、信號(hào)的分類
Linux系統(tǒng)中的信號(hào)有兩類:標(biāo)準(zhǔn)信號(hào)和實(shí)時(shí)信號(hào)黄琼。
標(biāo)準(zhǔn)信號(hào)是傳統(tǒng)Unix系統(tǒng)中的信號(hào),編號(hào)范圍從1到31。
實(shí)時(shí)信號(hào)是Linux獨(dú)有的信號(hào)脏款,編號(hào)范圍從32到64围苫。
三、信號(hào)的使用
1撤师、注冊(cè)信號(hào)處理函數(shù)
在C語(yǔ)言中剂府,可以使用signal函數(shù)來(lái)注冊(cè)信號(hào)處理函數(shù)。signal函數(shù)原型如下:
void (*signal(int signum, void (*handler)(int)))(int);
其中剃盾,signum參數(shù)表示要注冊(cè)的信號(hào)編號(hào)腺占,handler參數(shù)表示信號(hào)處理函數(shù)。signal函數(shù)會(huì)返回上一次注冊(cè)的信號(hào)處理函數(shù)的地址痒谴。
下面是一個(gè)簡(jiǎn)單的例子衰伯,注冊(cè)SIGINT信號(hào)的處理函數(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;
}
在上面的例子中,我們首先定義了一個(gè)名為sigint_handler的函數(shù)积蔚,用于處理SIGINT信號(hào)意鲸。
在main函數(shù)中,我們使用signal函數(shù)注冊(cè)了SIGINT信號(hào)的處理函數(shù)尽爆。如果signal函數(shù)返回的值是SIG_ERR怎顾,表示注冊(cè)信號(hào)處理函數(shù)失敗。
在循環(huán)中漱贱,我們只是簡(jiǎn)單地輸出Hello World槐雾!字符串,并使用sleep函數(shù)暫停1秒鐘幅狮,以便觀察信號(hào)處理過(guò)程募强。
- 編譯并運(yùn)行,打印如下
[wayne@wayne:~]./signal
Hello World!
Hello World!
Hello World!
2彪笼、發(fā)送信號(hào)
2.1 kill函數(shù)
在Linux系統(tǒng)中钻注,可以使用kill函數(shù)向進(jìn)程發(fā)送信號(hào)。kill函數(shù)原型如下:
int kill(pid_t pid, int sig);
其中配猫,pid參數(shù)表示進(jìn)程的PID號(hào)幅恋,sig參數(shù)表示要發(fā)送的信號(hào)編號(hào)。如果pid參數(shù)的值是0泵肄,表示將信號(hào)發(fā)送給與當(dāng)前進(jìn)程屬于同一個(gè)進(jìn)程組的所有進(jìn)程捆交。
下面是一個(gè)例子,向指定進(jìn)程發(fā)送SIGINT信號(hào):
#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ù)不足,就打印使用說(shuō)明并退出程序冯丙。
然后我們將命令行參數(shù)轉(zhuǎn)換為進(jìn)程PID號(hào)肉瓦,并使用kill函數(shù)向該進(jìn)程發(fā)送SIGINT信號(hào)。如果kill函數(shù)返回-1,表示發(fā)送信號(hào)失敗泞莉。
- 編譯并運(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
// 此時(shí)上面運(yùn)行的signal進(jìn)程會(huì)收到信號(hào),打印如下信息
Received SIGINT signal!
2.2 kill命令
我們也可以在shell中鲫趁,用kill命令向進(jìn)程發(fā)送信號(hào)斯嚎,kill命令的語(yǔ)法如下:
kill [options] <pid>
其中,pid表示要發(fā)送信號(hào)的進(jìn)程PID號(hào)挨厚。options是一些可選參數(shù)堡僻,例如,可以使用-9參數(shù)發(fā)送SIGKILL信號(hào)疫剃。
我們可以打開一個(gè)新的終端窗口钉疫,使用ps命令查看本文介紹的示例程序的PID號(hào),然后使用kill命令向該進(jìn)程發(fā)送SIGINT信號(hào)慌申,示例如下:
$ 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號(hào)為5902陌选,然后使用kill命令向該進(jìn)程發(fā)送SIGINT信號(hào)(信號(hào)編號(hào)為2)。在執(zhí)行kill命令之后蹄溉,我們可以看到示例程序輸出了"Received SIGINT signal"這一行信息咨油,說(shuō)明信號(hào)處理函數(shù)已經(jīng)被正確調(diào)用了。
四柒爵、常用信號(hào)
Linux系統(tǒng)中常用的信號(hào)有很多役电,下面列出一些常用的信號(hào)及其含義:
信號(hào)編號(hào) | 信號(hào)名稱 | 含義 |
---|---|---|
1 | SIGHUP | 終端掛起或者控制進(jìn)程結(jié)束 |
2 | SIGINT | 中斷信號(hào),通常是CTRL-C |
3 | SIGQUIT | 終止信號(hào)棉胀,通常是CTRL-\ |
9 | SIGKILL | 強(qiáng)制終止進(jìn)程 |
11 | SIGSEGV | 段錯(cuò)誤 |
15 | SIGTERM | 終止信號(hào)法瑟,通常是kill命令發(fā)送的信號(hào) |
18 | SIGCONT | 繼續(xù)執(zhí)行被暫停的進(jìn)程 |
19 | SIGSTOP | 暫停進(jìn)程 |
20 | SIGTSTP | 終端掛起或者CTRL-Z |
五、小結(jié)
總的來(lái)說(shuō)唁奢,Linux 信號(hào)是一種用于通知進(jìn)程發(fā)生某個(gè)事件或錯(cuò)誤的機(jī)制霎挟,可以用于處理異常情況、進(jìn)程間通信等多種場(chǎng)景麻掸。
以上酥夭,如果覺得對(duì)你有幫助,點(diǎn)個(gè)贊再走吧脊奋,這樣@知微之見也有更新下去的動(dòng)力熬北!
也歡迎私信我,一起交流诚隙!