一、信號(hào)
1、信號(hào)通信
信號(hào)通信,其實(shí)就是內(nèi)核向用戶(hù)空間進(jìn)程發(fā)送信號(hào)。
- 只有內(nèi)核才能發(fā)信號(hào),用戶(hù)空間進(jìn)程不能發(fā)送信號(hào)。
- 信號(hào)已經(jīng)存在了,不需要進(jìn)行創(chuàng)建。
內(nèi)核空間有很多信號(hào)。
kill -l:查看內(nèi)核可以發(fā)送多少種信號(hào)
kill -9 pid:殺死某個(gè)進(jìn)程

每種信號(hào)的id號(hào) + 功能
2、信號(hào)通信的框架
- 信號(hào)的發(fā)送(發(fā)送信號(hào)進(jìn)程):kill raise alarm
- 信號(hào)的接收(接收信號(hào)進(jìn)程) : pause() sleep while(1)
- 信號(hào)的處理(接收信號(hào)進(jìn)程) : signal
二、信號(hào)的發(fā)送
1、kill函數(shù)

kill函數(shù)
Q:kill函數(shù)是如何實(shí)現(xiàn)的?
#include "sys/types.h"
#include "signal.h"
#include "unistd.h"
#include "stdio.h"
#include "stdlib.h"
int main(int argc, char *argv[])
{
int sig;
int pid;
if(argc < 3)
{
printf("please input param\n");
return -1;
}
sig = atoi(argv[1]); // atoi函數(shù):將字符串轉(zhuǎn)化為整數(shù)
pid = atoi(argv[2]);
printf("sig = %d, pid = %d\n", sig, pid);
return 0;
}

說(shuō)明字符串轉(zhuǎn)化為整數(shù)是成功的
2、raise函數(shù)
發(fā)信號(hào)給自己,而沒(méi)有發(fā)送給其他進(jìn)程。
相當(dāng)于kill(getpid(), sig)

raise函數(shù)
#include "stdio.h"
#include "sys/types.h"
#include "signal.h"
#include "stdio.h"
#include "stdlib.h"
int main()
{
printf("raise before\n"); // 該行會(huì)被打印
raise(9); // 把本進(jìn)程殺死
printf("raise after\n"); // 該行不會(huì)被打印
return 0;
}

image.png
3、alarm函數(shù)
alarm : 發(fā)送鬧鐘信號(hào)的函數(shù)。
alarm 與 raise 函數(shù)的比較:
相同點(diǎn):讓內(nèi)核發(fā)送信號(hào)給當(dāng)前進(jìn)程。
不同點(diǎn):
- alarm 只會(huì)發(fā)送SIGALARM信號(hào)
- alarm 會(huì)讓內(nèi)核定時(shí)一段時(shí)間之后發(fā)送信號(hào), raise會(huì)讓內(nèi)核立刻發(fā)信號(hào)

alarm函數(shù)
#include "stdio.h"
#include "sys/types.h"
#include "signal.h"
#include "stdio.h"
#include "stdlib.h"
int main()
{
int i = 0;
printf("alarm before\n");
alarm(9); // 定時(shí)9s,讓內(nèi)核發(fā)送SIGALARM信號(hào)
printf("alarm after\n");
while(i < 20) // 運(yùn)行20s
{
i++;
sleep(1);
printf("process things, i = %d\n", i);
}
return 0;
}

運(yùn)行結(jié)果
4、信號(hào)及其含義

信號(hào)及其含義.png
三、信號(hào)的接收
1、sleep函數(shù)
睡眠一段時(shí)間
2、pause函數(shù)
一直處于睡眠狀態(tài)

pause函數(shù)
#include "sys/types.h"
#include "signal.h"
#include "stdio.h"
#include "stdlib.h"
int main()
{
int i = 0;
printf("pause before\n");
pause(); // 一直睡眠
printf("pause after\n");
while(i < 20) // 運(yùn)行20s
{
i++;
sleep(1);
printf("process things, i = %d\n", i);
}
return 0;
}

pause一直睡眠
while(1)
四、信號(hào)的處理
收到信號(hào)的進(jìn)程,應(yīng)該怎樣處理? 處理的方式:
(1) 進(jìn)程的默認(rèn)處理方式(內(nèi)核為用戶(hù)進(jìn)程設(shè)置的默認(rèn)處理方式)
A:忽略
B:終止進(jìn)程
C:暫停
(2) 自己的處理方式:
自己處理信號(hào)的方法告訴內(nèi)核,這樣你的進(jìn)程收到了這個(gè)信號(hào)就會(huì)采用你自己的處理方式。
1、signal函數(shù)

signal函數(shù)
signal 函數(shù)有2個(gè)參數(shù),第1個(gè)參數(shù)是一個(gè)整形變量(信號(hào)值),告訴內(nèi)核處理哪個(gè)信號(hào);第2個(gè)參數(shù)是一個(gè)函數(shù)指針,是我們自己寫(xiě)的處理函數(shù),告訴內(nèi)核怎樣處理信號(hào)。
這個(gè)函數(shù)的返回值是一個(gè)函數(shù)指針。
#include "stdio.h"
#include "sys/types.h"
#include "signal.h"
#include "stdio.h"
#include "stdlib.h"
void myfun(int signum)
{
int i = 0;
while(i < 10)
{
printf("process signal signum = %d\n", signum);
sleep(1);
i++;
}
return; // 返回main函數(shù)
}
int main()
{
int i = 0;
signal(14, myfun); // 14號(hào)信號(hào)是SIGALARM信號(hào)
printf("alarm before\n");
alarm(9); // 定時(shí)9s,讓內(nèi)核發(fā)送SIGALARM信號(hào)
printf("alarm after\n");
while(i < 20) // 運(yùn)行20s
{
i++;
sleep(1);
printf("process things, i = %d\n", i);
}
return 0;
}

運(yùn)行結(jié)果-截圖1

運(yùn)行結(jié)果-截圖2