Linux(十二)信號

????????今天我們就要來一起學習信號啦!!!還記得小編在之前的文章中說過的ctrl+c嗎?之前小編沒有詳細介紹過,現在我們就要來學習啦!!!

一、信號的基本介紹

? ? ? ? 首先,小編帶領大家先一起學習一下什么是信號吧。

????????信號是系統響應某個條件而產生的事件,進程接收到信號會執行相應的操作

????????大家要注意,我們在使用信號時,是需要添加頭文件的。與信號有關的系統調用在<signal.h>頭文件中。

1、信號的存儲位置

舊版

vim /usr/include/x86_64-linux-gnu/bits/signum.h?

新版(23版)

vim /usr/include/x86_64-linux-gnu/bits/signum-arch.h

vim /usr/include/x86_64-linux-gnu/bits/signum-generic.h

2、常見信號對應的功能

SIGBORT? ? ? *進程異常終止

SIGALRM? ? ? 超時警告

SIGFPE? ? ? ? ?*浮點運算異常

SIGHUP? ? ? ? ?連接掛斷

SIGILL? ? ? ? ? ? *非法指令

SIGINT? ? ? ? ? ? 終端中斷

SIGKILL? ? ? ? ? ?終止進程(此信號不能被捕獲或忽略)

SIGPIPE? ? ? ? ??向無讀進程的管道寫數據

SIGQUIT? ? ? ? ??終端退出

SIGSEGV? ? ? ? ?*無效內存段訪問

SIGTERM? ? ? ? 終止

SIGUSR1? ? ? ? ?用戶定義信號1

SIGUSR2? ? ? ? ?用戶定義信號2

(在這里,重點的信號用了加粗提醒大家一定要記住,在這篇文章里,小編還不會向大家介紹SIGPIPE,在后面小編介紹管道時,會結合前邊的內容和新的內容全面介紹管道)

3、信號的值

? ? ? ? ? ? 信號名稱? 信號代號

#define SIGHUP 1

#define SIGINT?2? ? ?//鍵盤按下 Ctrl+c 時,會產生終端中斷信號

#define SIGQUIT?3? //鍵盤按下 Ctrl+\時,會產生終端退出信號

#define SIGILL?4

#define SIGTRAP?5

#define SIGABRT?6

#define SIGIOT?6

#define SIGBUS?7

#define SIGFPE?8

#define SIGKILL?9? ? ?//該信號的響應方式不允許改變

#define SIGUSR1?10

#define SIGSEGV?11

#define SIGUSR2?12

#define SIGPIPE?13? ? //讀端關閉的描述符,寫端寫入時產生,該信號會終止程序(向無讀進程的管道寫數據)

#define SIGALRM?14

#define SIGTERM?15? ? //系統 kill 命令默認發送的信號

#define SIGSTKFLT?16

#define SIGCHLD?17? ? ?//子進程結束后,內核會默認給父進程發送該信號

#define SIGCONT?18

#define SIGSTOP?19

#define SIGSTP?20

#define SIGTTIN?21

#define SIGTTOU?22

#define SIGURG?23

(通過這個,小編是想告訴大家,這些信號其實對應的就是數字)

二、信號的響應方式

信號有三種響應方式:默認、忽略、自定義

1、信號處理函數

????????在Linux系統中,我們想要了解一個新的知識必不可少的就是幫助手冊啦!!!大家還記得怎么使用嗎?

? ? ? ? 答案就是:man signal

2、?三種響應方式

(1)默認

????????如果signal函數的參數為?SIG_DFL,則系統將使用默認的信號處理動作。

? ? ? ? 大家可以輸入命令“man 7 signal”查看默認處理方式,當然啦,小編也會為大家展示出來。

????????在上圖,小編只截取了剛剛加粗的幾個信號,想看完整的小伙伴可以自己輸入命令“man 7 signal”,往下翻就能看到啦。

(2)忽略

????????如果signal函數的參數為?SIG_IGN,則系統將忽略該信號。

(3)自定義

????????信號自定義處理,其實是對信號進行捕捉,然后讓信號執行自定義的方法。

下面,小編向大家演示一下默認的處理方式(也就是收到信號后,進程按照信號默認的方式去處理)

#include<stdio.h>
#include<stdlib.h>
#include<unistd.h>
#include<assert.h>
#include<signal.h>
int main()
{while(1){printf("main run\n");sleep(1);}   exit(0);
}

在上述代碼中,小編寫了一個while(1)的循環,會一直執行, 當我們鍵盤按下ctrl+c時,其實就是因為該進程收到了一個信號:SIGNT——終端中斷的信號(2號信號);就是說,在鍵盤上按下ctrl+c時,會給當前終端前臺執行的進程發送SIGINT信號;

3、改變型號的響應方式

(1)將默認改為自定義

#include<stdio.h>
#include<stdlib.h>
#include<unistd.h>
#include<assert.h>
#include<signal.h>
#include<string.h>
void sig_fun(int sig)
{printf("sig=%d\n",sig);
}
int main()
{signal(SIGINT,sig_fun);//這里不是調用,這里是作約定while(1){printf("main run\n");sleep(1);}   exit(0);
}

?那我們該如何結束進程呢?

方法一(圖上方法):我們可以通過ctrl+\這個是終端退出的信號

方法二:打開另外一個終端,通過ps -eflgrep test[test是程序名,可替換]這個命令找到該進程的pid,然后kill掉它。(這也是我們在前面學習kill時掌握的方法)

(2)將默認改為忽略

#include<stdio.h>
#include<stdlib.h>
#include<unistd.h>
#include<assert.h>
#include<signal.h>
#include<string.h>
int main()
{signal(SIGINT,SIG_IGN);//這里不是調用,這里是作約定while(1){   printf("main run\n");sleep(1);}   exit(0);
}

4、SIGCHLD信號

(1)子進程結束,父進程會收到內核發送的SIGCHLD信號(注意:內核發送)

大家還記得我們在學習fork復制進程中的父子進程時用到的代碼嗎?

小編把代碼放到這里幫助大家回顧昂

#include <stdio.h>
#include <unistd.h>
#include <signal.h>
#include <stdlib.h>int main(){char *s=NULL;int n=0;pid_t id=fork();if(pid==-1){printf("fork err\n");exit(1);}if(id == 0){s="child";n=3;}//子進程else{s="parent";n=7;}//父進程int i=0;for(;i<n;i++){printf("s=%s\n",s);sleep(1);}exit(0);
}

在學習僵死進程時,小編說過父進程沒有獲取退出碼是會產生僵死進程的;

在上面這段代碼里,其實子進程結束了,已經給父進程發送了一個信號.只不過父進程忽略了;那么,我們修改一下代碼,讓父進程收到子進程的代碼,打印一下收到的信號代號,不要忽略掉;

#include<stdio.h>
#include<stdlib.h>
#include<unistd.h>
#include<signal.h>void sig_fun(int sig)
{printf("sig = %d\n",sig);printf("child over!\n");
}
int main()
{int n=0;char *s = NULL;pid_t pid=fork();if(pid == -1) {   printf("fork err\n");exit(1);}   if(pid==0){   n=3;s="child";}   else{   signal(SIGCHLD,sig_fun);//子進程結束,內核會默認給父進程發送信號n=7;s="parent";}for(int i =0;i<n;i++){printf("s=%s\n",s);sleep(1);}exit(0);
}

????????由執行結果可以看出,子進程結束,確實是會給父進程發送17號信號SIGCHLD;只不過遇到默認情況,父進程不會理會而已;所以,這個17號信號的默認方式就是忽略;
????????再次強調一下,這個不是子進程發送的信號,是內核發送的信號;

大家還記得處理僵死進程的兩種方法

(1)父進程先結束(2)父進程調用wait()方法獲取子進程的退出碼

兩個方法的本質是一樣的,但是方法二會阻塞,就是父進程在等子進程結束,才會獲取退出
碼。結合信號,如何處理,讓它不再阻塞呢?

父進程調用wait是配合信號使用的。讓我們通過下面的代碼觀察一下吧!

#include<stdio.h>
#include<stdlib.h>
#include<unistd.h>
#include<signal.h>
#include<wait.h>//注意,wait的頭文件不要忘記void sig_fun(int sig)
{printf("sig = %d\n",sig);printf("child over!\n");int val;wait(&val);//我們也可以簡單寫,就是不獲取退出碼,只要不變成僵死進程就可以//wait(NULL);
}
int main()
{int n=0;char *s = NULL;pid_t pid=fork();if(pid == -1) {   printf("fork err\n");exit(1);}   if(pid==0){   n=3;s="child";}else{signal(SIGCHLD,sig_fun);//子進程結束,內核會默認給父進程發送信號n=7;s="parent";}for(int i =0;i<n;i++){printf("s=%s\n",s);sleep(1);}exit(0);
}

?

三、信號實例練習

1、收到SIGINT這個信號,第一次打印信號的代號,第二次按照默認形式把進程結束

#include<stdio.h>
#include<stdlib.h>
#include<unistd.h>
#include<assert.h>
#include<string.h>
#include<signal.h>
void sig_fun(int sig)
{printf("sig = %d\n",sig);signal(sig,SIG_DFL);
}
int main(){signal(SIGINT,sig_fun);//這里不是調用,這里是作約定while(1){   printf("main run\n");sleep(1);}   exit(0);
}

?

2、自己實現kill命令

(1)系統調用kill與kill命令

kill也是一個命令,它底層就封裝了我們的系統調用kill;

所以,man kill是1命令,man 2 kill才是系統調用;

man 2 kill得到原型:

int kill(pid_t pid,int sig);
就是向PID為pid的發送sig信號;
返回值為-1說明失敗,0表示成功.

(2)回顧kill命令

????????執行kill PID命令,這個就是系統調用,默認發送了15號信號。比如我們sleep 500,然后
打開另外一個終端kill掉它,這個kill就是默認發送了15號信號。

(3)實現kill命令

自己實現kill命令,需要PID,需要信號代號。就是我們也要寫一個類似kill-9 PID 的命令;為什么需要信號代號呢?

9號信號是一個特殊的信號,它是不允許改變響應方式的。

比如暫停進程(ctrl+Z),那么kill不掉,就需要9號信號強制結束。

寫一個類似kill-9 PID的命令;(./mykill PID SIG)

#include<stdio.h>
#include<stdlib.h>
#include<unistd.h>
#include<assert.h>
#include<signal.h>//./mykill pid 信號代號
int main(int argc,char *argv[])
{if(argc!=3){printf("argc error!\n");return -1; }   int pid  = 0;int sig = 0;sscanf(argv[1],"%d",&pid);sscanf(argv[2],"%d",&sig);if(kill(pid,sig)==-1){   perror("kill error!\n");//perror是打印出錯信息,輸出錯誤原因}   exit(0);
}

?

(4)15號信號和9號信號

????????運行sleep 500這個進程,發現使用自己的mykill命令發送15號信號顯示的是“已終止(Terminated)",發現使用自己的mykill命令發送9號信號是“已殺死(killed)",和系統的kill命令是一樣的。

????????那可能有小伙伴就會說kill命令沒有傳遞信號代號,其實是一樣的,也就是mykill傳遞兩個參數即可,把信號代號也就是argv[2]定義成15,或者9即可。

? ? ? ? 在這里小編想補充一下,其實19號信號也不能被忽略,它是暫停進程。

【小編有話說】

? ? ? ??本次內容就要結束啦,截止到這篇文章,小編其實已經帶領大家自己寫了兩個命令了,分別是mycp和mykill,還有小伙伴記得嘛,mycp是在讀寫操作那里實現的。小編現在正在籌備一個關于LINUX項目的文章,大概可能會再過兩篇Linux文章就會發布啦,到時后希望小伙伴們能夠多多捧場呀!!!

????????最后還是老三樣,點贊收藏和關注~

????????喜歡小編的文章就不要忘記這三樣,點贊收藏加關注,找到小編不迷路~

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/pingmian/75515.shtml
繁體地址,請注明出處:http://hk.pswp.cn/pingmian/75515.shtml
英文地址,請注明出處:http://en.pswp.cn/pingmian/75515.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

Dify開發實戰-自制插件 和安裝python3最新版本 記錄版本 后續會持續更新

自定義插件 Dify 插件腳手架工具Python 環境&#xff0c;版本號 ≥ 3.12 安裝Python 一 進入官網 https://www.python.org/downloads/windows/ 點擊下載 二、安裝python&#xff08;本文中有借鑒其他圖片 所以圖片展示python版本可能不一致 請忽略&#xff09; 1.雙擊打開py…

Docker安裝、配置Redis

1.如果沒有docker-compose.yml文件的話&#xff0c;先創建docker-compose.yml 配置文件一般長這個樣子 version: 3services:redis:image: redis:latestcontainer_name: redisports:- "6379:6379"command: redis-server --requirepass "123456"restart: a…

Parasoft C++Test軟件單元測試_操作指南

系列文章目錄 Parasoft C++Test軟件靜態分析:操作指南(編碼規范、質量度量)、常見問題及處理 Parasoft C++Test軟件單元測試:操作指南、實例講解、常見問題及處理 Parasoft C++Test軟件集成測試:操作指南、實例講解、常見問題及處理 進階擴展:自動生成靜態分析文檔、自動…

二級索引詳解

二級索引詳解 二級索引(Secondary Index)是數據庫系統中除主鍵索引外的附加索引結構,用于加速基于非主鍵列的查詢操作。以下是關于二級索引的全面解析: 一、核心概念 特性主鍵索引 (Primary Index)二級索引 (Secondary Index)唯一性必須唯一可以唯一或非唯一數量每表只有…

Python_level1_字符串_11

目錄 一、基本概念 二、字符串基本操作&#xff1a;【索引、切片、遍歷】 1.字符串與列表&#xff08;相同&#xff09; 1&#xff09;索引&#xff08;從0開始&#xff09;(可以獲取某一個/某幾個連續的字符) 2&#xff09;切片 [xx:xx] 與 列表 語法規則一樣 [起…

Axure數據可視化科技感大屏設計資料——賦能多領域,展示無限價值

可視化大屏如何高效、直觀地展示數據&#xff0c;并將其轉化為有價值的決策依據&#xff0c;成為了許多企業和組織面臨的共同挑戰。Axure大屏可視化模板&#xff0c;作為一款強大的數據展示工具&#xff0c;正在以其出色的交互性和可定制性&#xff0c;賦能多個領域&#xff0c…

MySQL 性能調優:數據庫的極限運動訓練

就像運動員需要不斷訓練才能突破極限&#xff0c;數據庫也需要各種調優才能跑得更快…讓我們一起給 MySQL 安排一套專業的"健身計劃"&#xff01; 什么是 MySQL 性能調優&#xff1f;&#x1f914; MySQL 性能調優是指通過各種配置優化、結構調整和查詢改進&#x…

4.5/Q1,GBD數據庫最新文章解讀

文章題目&#xff1a;Emerging trends and cross-country health inequalities in congenital birth defects: insights from the GBD 2021 study DOI&#xff1a;10.1186/s12939-025-02412-7 中文標題&#xff1a;先天性出生缺陷的新趨勢和跨國健康不平等&#xff1a;GBD 202…

基于DeepSeek、ChatGPT支持下的地質災害風險評估、易發性分析、信息化建庫及災后重建

前言&#xff1a; 地質災害是指全球地殼自然地質演化過程中&#xff0c;由于地球內動力、外動力或者人為地質動力作用下導致的自然地質和人類的自然災害突發事件。在降水、地震等自然誘因的作用下&#xff0c;地質災害在全球范圍內頻繁發生。我國不僅常見滑坡災害&#xff0c;還…

Linux | 安裝超級終端串口軟件連接i.MX6ULL開發板(8)

01 它的安裝步驟也非常簡單,安裝語言選擇中文簡體,點擊確定,如下圖所示。 點擊下一步,如下圖所示。 02

藍橋杯15屆 寶石組合

問題描述 在一個神秘的森林里&#xff0c;住著一個小精靈名叫小藍。有一天&#xff0c;他偶然發現了一個隱藏在樹洞里的寶藏&#xff0c;里面裝滿了閃爍著美麗光芒的寶石。這些寶石都有著不同的顏色和形狀&#xff0c;但最引人注目的是它們各自獨特的 “閃亮度” 屬性。每顆寶…

Lua:第1-4部分 語言基礎

1 Lua語言入門 1.1 程序段 我們將 Lua 語言執行的每一段代碼&#xff08;例如&#xff0c;一個文件或交互模式下的一行&#xff09;稱為一個程序段 &#xff08; Chunk &#xff09; &#xff0c;即一組命令或表達式組成的序列 。 1.2 一些詞法規范 Lua 語言中的標識符&#…

CTF類題目復現總結-hashcat 1

一、題目地址 https://buuoj.cn/challenges#hashcat二、復現步驟 1、下載附件&#xff0c;解壓得到What kind of document is this_文件&#xff1b; 2、用010 Editor打開What kind of document is this_文件&#xff0c;發現是office文件&#xff1b; 3、將后綴名改為ppt時…

手機歸屬地查詢Api接口,數據準確可靠

手機歸屬地查詢是一項非常實用的功能&#xff0c;它可以幫助我們快速了解一個手機號碼的所屬地區、區號、郵政編碼等信息。在互聯網時代&#xff0c;隨著大數據和人工智能技術的發展&#xff0c;手機歸屬地查詢的API接口也變得越來越普及和便捷。 在本文中&#xff0c;我們將介…

orangepi zero燒錄及SSH聯網

下載對應版本的armbian鏡像 armbian的默認用戶root&#xff0c;默認密碼&#xff1a;1234 下載燒錄工具win32diskimager https://sourceforge.net/projects/win32diskimager/files/Archive/ 插入16G以上TF卡&#xff0c;使用win32diskimager燒錄armbian鏡像 燒錄完畢后用l…

為什么有的深度學習訓練,有訓練集、驗證集、測試集3個劃分,有的只是劃分訓練集和測試集?

在機器學習和深度學習中&#xff0c;數據集的劃分方式取決于任務需求、數據量以及模型開發流程的嚴謹性。 1. 三者劃分&#xff1a;訓練集、驗證集、測試集 目的 訓練集&#xff08;Training Set&#xff09;&#xff1a;用于模型參數的直接訓練。驗證集&#xff08;Validati…

Linux驅動開發 塊設備

目錄 序言 1.塊設備結構 分區(gendisk) 請求(request) 請求隊列 1. 多隊列架構 2. 默認限制與擴展 bio 2.塊設備的使用 頭文件與宏定義 blk-mq 相關結構和操作 塊設備操作函數 模塊初始化函數 模塊退出函數 3.總結 序言 塊設備&#xff08;如硬盤、虛擬盤&#x…

ResNet改進(14):添加 EMA注意力機制提升跨空間學習效率

本專欄代碼均經過測試,可以直接替換項目中的模型,一鍵運行! 采用最新的即插即用模塊,有效漲點!! 1.EMA注意力機制 EMA(Efficient Multi-scale Attention)注意力機制是一種創新的注意力設計,能夠有效提升模型在跨空間學習任務中的表現。以下是對該機制的詳細解析: EM…

計算機硬件——CPU 主要參數

什么是 CPU &#xff1f; CPU 的英文全稱是 Central Processing Unit&#xff0c;即中央處理器。CPU 的內部結構可分為控制單元、邏輯單元和存儲單元三大部分。CPU 的性能大致上反映出了它所配置的微機的性能&#xff0c;因此 CPU 的性能指標十分重要。 CPU 的主要參數 CPU …

針對 Python 3.7.0,以下是 Selenium 版本的兼容性建議和安裝步驟

1. Selenium 版本推薦 最高兼容版本&#xff1a; Selenium 4.11.2&#xff08;官方明確支持 Python 3.7&#xff0c;但需注意部分新功能可能受限&#xff09;。 穩定兼容版本&#xff1a; Selenium 3.141.0&#xff08;經典版本&#xff0c;完全兼容 Python 3.7&#xff0c;適…