国产 无码 综合区,色欲AV无码国产永久播放,无码天堂亚洲国产AV,国产日韩欧美女同一区二区

Linux進(jìn)程信號(hào)【信號(hào)產(chǎn)生】

這篇具有很好參考價(jià)值的文章主要介紹了Linux進(jìn)程信號(hào)【信號(hào)產(chǎn)生】。希望對(duì)大家有所幫助。如果存在錯(cuò)誤或未考慮完全的地方,請(qǐng)大家不吝賜教,您也可以點(diǎn)擊"舉報(bào)違法"按鈕提交疑問。

?個(gè)人主頁(yè): 北 海
??所屬專欄: Linux學(xué)習(xí)之旅
??操作環(huán)境: CentOS 7.6 阿里云遠(yuǎn)程服務(wù)器

Linux進(jìn)程信號(hào)【信號(hào)產(chǎn)生】



??前言

Linux 中,進(jìn)程具有獨(dú)立性,進(jìn)程在運(yùn)行后可能 “放飛自我”,這是不利于管理的,于是需要一種約定俗成的方式來控制進(jìn)程的運(yùn)行,這就是 進(jìn)程信號(hào),本文將會(huì)從什么是進(jìn)程信號(hào)開篇,講述各種進(jìn)程信號(hào)的產(chǎn)生方式及作用

不同的信號(hào)指示燈代表著不同的執(zhí)行動(dòng)作

Linux進(jìn)程信號(hào)【信號(hào)產(chǎn)生】


???正文

1、進(jìn)程信號(hào)基本概念

1.1、什么是信號(hào)?

信號(hào) 是信息傳遞的承載方式,一種信號(hào)往往代表著一種執(zhí)行動(dòng)作,比如:

  • 雞叫 => 天快亮了
  • 鬧鐘 => 起床、完成任務(wù)
  • 紅綠燈 => 紅燈停,綠燈行
  • ……

Linux進(jìn)程信號(hào)【信號(hào)產(chǎn)生】

當(dāng)然這些都是生活中的 信號(hào),當(dāng)產(chǎn)生這些 信號(hào) 時(shí),我們會(huì)立馬想到對(duì)應(yīng)的 動(dòng)作 ,這是因?yàn)?我們認(rèn)識(shí)并能處理這些信號(hào)

我們能進(jìn)行處理是因?yàn)槭苓^教育,學(xué)習(xí)了執(zhí)行動(dòng)作,但對(duì)進(jìn)程來說,它可沒有接受過九年義務(wù)教育,也不知道什么時(shí)候該干什么事

于是程序員們給操作系統(tǒng)植入了一批 指令,一個(gè)指令表示一種特殊動(dòng)作,而這些指令就是 信號(hào)(進(jìn)程信號(hào))

通過 kill -l 查看當(dāng)前系統(tǒng)中的信號(hào)集合表

kill -l

Linux進(jìn)程信號(hào)【信號(hào)產(chǎn)生】
這些就是當(dāng)前系統(tǒng)中的 進(jìn)程信號(hào),一共 62 個(gè),其中 1~31 號(hào)信號(hào)為 普通信號(hào)(學(xué)習(xí)目標(biāo)),用于 分時(shí)操作系統(tǒng);剩下的 34~64 號(hào)信號(hào)為 實(shí)時(shí)信號(hào),用于 實(shí)時(shí)操作系統(tǒng)

  • 分時(shí)操作系統(tǒng):根據(jù)時(shí)間片實(shí)行公平調(diào)度,適用于個(gè)人電腦
  • 實(shí)時(shí)操作系統(tǒng):高響應(yīng),適合任務(wù)較少、需要快速處理的平臺(tái),比如汽車車機(jī)、火箭發(fā)射控制臺(tái)

實(shí)時(shí)操作系統(tǒng)

Linux進(jìn)程信號(hào)【信號(hào)產(chǎn)生】

普通信號(hào)只保存它有無(wú)產(chǎn)生,實(shí)時(shí)信號(hào)可以保持很長(zhǎng)時(shí)間

因?yàn)槲覀兊南到y(tǒng)屬于 分時(shí)操作系統(tǒng),所以只需要研究 1~31 號(hào)信號(hào)即可,當(dāng)然也不是全部研究,部分信號(hào)只做了解即可

1.2、信號(hào)的作用

早在 《Linux進(jìn)程學(xué)習(xí)【進(jìn)程狀態(tài)】》 我們就已經(jīng)使用過 信號(hào) 了,比如:

  • kill -9 pid 終止進(jìn)程運(yùn)行
  • kill -19 pid 暫停進(jìn)程運(yùn)行
  • kill -18 pid 恢復(fù)進(jìn)程運(yùn)行

就連常用的 ctrl+cctrl+d 熱鍵本質(zhì)上也是 信號(hào)

這么多信號(hào),其對(duì)應(yīng)功能是什么呢?

  • 可以通過 man 7 signal 進(jìn)行查詢
man 7 signal

Linux進(jìn)程信號(hào)【信號(hào)產(chǎn)生】

簡(jiǎn)單總結(jié)一下,1~31 號(hào)信號(hào)對(duì)應(yīng)的功能如下(表格內(nèi)容引用自 2021dragon Linux中的31個(gè)普通信號(hào))

信號(hào)編號(hào) 信號(hào)名 功能
1 SIGHUP 如果終端接口檢測(cè)到一個(gè)連接斷開,則會(huì)將此信號(hào)發(fā)送給與該終端相關(guān)的控制進(jìn)程,該信號(hào)的默認(rèn)處理動(dòng)作是終止進(jìn)程
2 SIGINT 當(dāng)用戶按組合鍵(一般采用 Ctrl + C )時(shí),終端驅(qū)動(dòng)程序產(chǎn)生此信號(hào)并發(fā)送至前臺(tái)進(jìn)程組中的每一個(gè)進(jìn)程,該信號(hào)的默認(rèn)處理動(dòng)作是終止進(jìn)程
3 SIGQUIT 當(dāng)用戶按組合鍵(一般采用 Ctrl + \ )時(shí),終端驅(qū)動(dòng)程序產(chǎn)生此信號(hào)并發(fā)送至前臺(tái)進(jìn)程組中的每一個(gè)進(jìn)程,該信號(hào)不僅終止前臺(tái)進(jìn)程組,同時(shí)會(huì)產(chǎn)生一個(gè) core 文件
4 SIGILL 此信號(hào)表示進(jìn)程已執(zhí)行一條非法指令,該信號(hào)的默認(rèn)處理動(dòng)作是終止進(jìn)程,同時(shí)產(chǎn)生一個(gè) core 文件
5 SIGTRAP 該信號(hào)由斷點(diǎn)指令或其他 trap 指令產(chǎn)生,該信號(hào)的默認(rèn)處理動(dòng)作是終止進(jìn)程,同時(shí)會(huì)產(chǎn)生一個(gè) core 文件
6 SIGABRT 調(diào)用 abort 函數(shù)是產(chǎn)生此信號(hào),進(jìn)程異常終止,同時(shí)會(huì)產(chǎn)生一個(gè) core 文件
7 SIGBUS 當(dāng)出現(xiàn)某些類型的內(nèi)存故障時(shí),常常產(chǎn)生該信號(hào),,該信號(hào)的默認(rèn)處理動(dòng)作是終止進(jìn)程,同時(shí)產(chǎn)生一個(gè) core 文件
8 SIGFPE 此信號(hào)表示一個(gè)算術(shù)運(yùn)算異常,比如除0、浮點(diǎn)溢出等,該信號(hào)的默認(rèn)處理動(dòng)作是終止進(jìn)程,同時(shí)產(chǎn)生一個(gè) core 文件
9 SIGKILL 該信號(hào)不能被捕捉或忽略,它向系統(tǒng)管理員提供了一種可以殺死任一進(jìn)程的可靠方法
10 SIGUSR1 這是一個(gè)用戶定義的信號(hào),即程序員可以在程序中定義并使用該信號(hào),該信號(hào)的默認(rèn)處理動(dòng)作是終止進(jìn)程
11 SIGSEGV 指示進(jìn)程進(jìn)行了一次無(wú)效的內(nèi)存訪問(比如訪問了一個(gè)未初始化的指針),該信號(hào)的默認(rèn)處理動(dòng)作是終止進(jìn)程并產(chǎn)生一個(gè) core 文件
12 SIGUSR2 這是另一個(gè)用戶定義的信號(hào),與 SIGUSR1 相似,該信號(hào)的默認(rèn)處理動(dòng)作是終止進(jìn)程
13 SIGPIPE 如果在管道的讀進(jìn)程已終止時(shí)對(duì)管道進(jìn)行寫入操作,則會(huì)收到此信號(hào),該信號(hào)的默認(rèn)處理動(dòng)作是終止進(jìn)程
14 SIGALRM 當(dāng)用 alarm 函數(shù)設(shè)置的定時(shí)器超時(shí)時(shí)產(chǎn)生此信號(hào),或由 setitimer 函數(shù)設(shè)置的間隔時(shí)間已經(jīng)超時(shí)時(shí)也產(chǎn)生會(huì)此信號(hào)
15 SIGTERM 該信號(hào)是由應(yīng)用程序捕獲的,使用該信號(hào)讓程序有機(jī)會(huì)在退出之前做好清理工作。與 SIGKILL 信號(hào)不同的是,該信號(hào)可以被捕捉或忽略,通常用來表示程序正常退出
16 SIGSTKFLT 該信號(hào)指示協(xié)處理器上的堆棧故障(未使用),該信號(hào)的默認(rèn)處理動(dòng)作是終止進(jìn)程
17 SIGCHLD 在一個(gè)進(jìn)程終止或停止時(shí),SIGCHLD 信號(hào)被發(fā)送給其父進(jìn)程。按系統(tǒng)默認(rèn),將忽略此信號(hào)。如果父進(jìn)程希望被告知其子進(jìn)程的這種狀態(tài)改變,則應(yīng)捕捉此信號(hào)。信號(hào)捕捉函數(shù)中通常要調(diào)用一種 wait 函數(shù)以取得子進(jìn)程 PID 及其終止?fàn)顟B(tài)
18 SIGCONT 可以通過發(fā)送該信號(hào)讓一個(gè)停止的進(jìn)程繼續(xù)運(yùn)行
19 SIGSTOP 這時(shí)一個(gè)作業(yè)控制信號(hào),該信號(hào)用于停止一個(gè)進(jìn)程,類似于交互停止信號(hào)( SIGTSTP ),但是該信號(hào)不能被捕捉或忽略
20 SIGTSTP 交互停止信號(hào),當(dāng)用戶按組合鍵(一般采用 Ctrl+Z )時(shí),終端驅(qū)動(dòng)程序產(chǎn)生此信號(hào)并發(fā)送至前臺(tái)進(jìn)程組中的每一個(gè)進(jìn)程
21 SIGTTIN 后臺(tái)進(jìn)程讀終端控制臺(tái)時(shí),由終端驅(qū)動(dòng)程序產(chǎn)生此信號(hào)并發(fā)送給該后臺(tái)進(jìn)程,該信號(hào)的默認(rèn)處理動(dòng)作是暫停進(jìn)程
22 SIGTTOU 后臺(tái)進(jìn)程向終端控制臺(tái)輸出數(shù)據(jù),由終端驅(qū)動(dòng)程序產(chǎn)生此信號(hào)并發(fā)送給該后臺(tái)進(jìn)程,該信號(hào)的默認(rèn)處理動(dòng)作是暫停進(jìn)程
23 SIGURG 套接字上有緊急數(shù)據(jù)時(shí),向當(dāng)前正在運(yùn)行的進(jìn)程發(fā)出此信號(hào),報(bào)告有緊急數(shù)據(jù)到達(dá),該信號(hào)的默認(rèn)處理動(dòng)作是忽略
24 SIGXCPU 進(jìn)程執(zhí)行時(shí)間超過了分配給該進(jìn)程的 CPU 時(shí)間,系統(tǒng)產(chǎn)生該信號(hào)并發(fā)送給該進(jìn)程,該信號(hào)的默認(rèn)處理動(dòng)作是終止進(jìn)程,同時(shí)會(huì)產(chǎn)生一個(gè) core 文件
25 SIGXFSZ 如果進(jìn)程寫文件時(shí)超過了文件的最大長(zhǎng)度設(shè)置,則會(huì)收到該信號(hào),該信號(hào)的默認(rèn)處理動(dòng)作是終止進(jìn)程,同時(shí)會(huì)產(chǎn)生一個(gè) core 文件
26 SIGVTALRM 虛擬時(shí)鐘超時(shí)時(shí)產(chǎn)生該信號(hào),與 SIGALRM 信號(hào)類似,但是該信號(hào)只計(jì)算該進(jìn)程占用 CPU 的使用時(shí)間,該信號(hào)的默認(rèn)處理動(dòng)作是終止進(jìn)程
27 SIGPROF 該信號(hào)類似與 SIGVTALRM,它不僅包括該進(jìn)程占用 CPU 的時(shí)間還包括執(zhí)行系統(tǒng)調(diào)用的時(shí)間,該信號(hào)的默認(rèn)處理動(dòng)作是終止進(jìn)程
28 SIGWINCH 當(dāng)窗口大小發(fā)生變化時(shí),內(nèi)核會(huì)將該信號(hào)發(fā)送至前臺(tái)進(jìn)程組,該信號(hào)的默認(rèn)處理動(dòng)作是忽略
29 SIGIO 此信號(hào)指示一個(gè)異步 I/O 事件,該信號(hào)的默認(rèn)處理動(dòng)作是終止進(jìn)程
30 SIGPWR 電源故障,該信號(hào)的默認(rèn)處理動(dòng)作是終止進(jìn)程
31 SIGSYS 該信號(hào)指示一個(gè)無(wú)效的系統(tǒng)調(diào)用,該信號(hào)的默認(rèn)處理動(dòng)作是終止進(jìn)程,同時(shí)會(huì)產(chǎn)生一個(gè) core 文件

注意:其中的 9 號(hào) 和 19 號(hào)信號(hào)是非常特殊的,不能修改其默認(rèn)動(dòng)作

1.3、信號(hào)的基本認(rèn)知

進(jìn)程信號(hào)由 信號(hào)編號(hào) + 執(zhí)行動(dòng)作 構(gòu)成,一個(gè)信號(hào)對(duì)應(yīng)一種動(dòng)作,對(duì)于進(jìn)程來說,動(dòng)作無(wú)非就這幾種:終止進(jìn)程、暫停進(jìn)程、恢復(fù)進(jìn)程3 個(gè)信號(hào)就夠用了啊,為什么要搞這么多信號(hào)?

  • 創(chuàng)造信號(hào)的目的不只是控制進(jìn)程,還要便于管理進(jìn)程,進(jìn)程的終止原因有很多種,如果一概而論的話,對(duì)于問題分析是非常不友好的,所以才會(huì)將信號(hào)細(xì)分化,搞出這么多信號(hào),目的就是為了方便定位、分析、解決問題
  • 并且 普通信號(hào) 就 31 個(gè),這就是意味著所有普通信號(hào)都可以存儲(chǔ)在一個(gè) int 中,表示是否收到該信號(hào)(信號(hào)的保存)

所以信號(hào)被細(xì)化了,不同的信號(hào)對(duì)應(yīng)不同的執(zhí)行動(dòng)作,雖然大部分最終都是終止進(jìn)程

進(jìn)程的執(zhí)行動(dòng)作是可修改的,默認(rèn)為系統(tǒng)預(yù)設(shè)的 默認(rèn)動(dòng)作

  1. 默認(rèn)動(dòng)作
  2. 忽略
  3. 自定義動(dòng)作

所以我們可以 更改信號(hào)的執(zhí)行動(dòng)作(后面會(huì)專門講信號(hào)處理相關(guān)內(nèi)容)

信號(hào)有這么多個(gè),并且多個(gè)進(jìn)程可以同時(shí)產(chǎn)生多個(gè)信號(hào),操作系統(tǒng)為了管理,先描述、再組織,在 PCB 中增加了 信號(hào)相關(guān)的數(shù)據(jù)結(jié)構(gòu):signal_struct,在這個(gè)結(jié)構(gòu)體中,必然存在一個(gè) 位圖結(jié)構(gòu) uint32_t signals 存儲(chǔ) 1~31 號(hào)信號(hào)的有無(wú)信息

//信號(hào)結(jié)構(gòu)體源碼(部分)
struct signal_struct {
	atomic_t		sigcnt;
	atomic_t		live;
	int			nr_threads;

	wait_queue_head_t	wait_chldexit;	/* for wait4() */

	/* current thread group signal load-balancing target: */
	struct task_struct	*curr_target;

	/* shared signal handling: */
	struct sigpending	shared_pending;

	/* thread group exit support */
	int			group_exit_code;
	/* overloaded:
	 * - notify group_exit_task when ->count is equal to notify_count
	 * - everyone except group_exit_task is stopped during signal delivery
	 *   of fatal signals, group_exit_task processes the signal.
	 */
	int			notify_count;
	struct task_struct	*group_exit_task;

	/* thread group stop support, overloads group_exit_code too */
	int			group_stop_count;
	unsigned int		flags; /* see SIGNAL_* flags below */

	/*
	 * PR_SET_CHILD_SUBREAPER marks a process, like a service
	 * manager, to re-parent orphan (double-forking) child processes
	 * to this process instead of 'init'. The service manager is
	 * able to receive SIGCHLD signals and is able to investigate
	 * the process until it calls wait(). All children of this
	 * process will inherit a flag if they should look for a
	 * child_subreaper process at exit.
	 */
	unsigned int		is_child_subreaper:1;
	unsigned int		has_child_subreaper:1;

	//……
};

下面對(duì) 進(jìn)程信號(hào) 做一波概念性的總結(jié)

1.信號(hào)是執(zhí)行的動(dòng)作的信息載體,程序員在設(shè)計(jì)進(jìn)程的時(shí)候,早就已經(jīng)設(shè)計(jì)了其對(duì)信號(hào)的識(shí)別能力
2.信號(hào)對(duì)于進(jìn)程來說是異步的,隨時(shí)可能產(chǎn)生,如果信號(hào)產(chǎn)生時(shí),進(jìn)程在處理優(yōu)先級(jí)更高的事情,那么信號(hào)就不能被立即處理,此時(shí)進(jìn)程需要保存信號(hào),后續(xù)再處理
3.進(jìn)程可以將 多個(gè)信號(hào) 或 還未處理 的信號(hào)存儲(chǔ)在 signal_struct 這個(gè)結(jié)構(gòu)體中,具體信號(hào)編號(hào),存儲(chǔ)在 uint32_t signals 這個(gè)位圖結(jié)構(gòu)中
4.所謂的 “發(fā)送” 信號(hào),其實(shí)就是寫入信號(hào),修改進(jìn)程中位圖結(jié)構(gòu)中對(duì)應(yīng)的比特位,由 0 置為 1,表示該信號(hào)產(chǎn)生了
5.signal_struct 屬于內(nèi)核數(shù)據(jù)結(jié)構(gòu),只能由 操作系統(tǒng) 進(jìn)行同一修改,無(wú)論信號(hào)是如何產(chǎn)生的,最終都需要借助 操作系統(tǒng) 進(jìn)行發(fā)送
6.信號(hào)并不是立即處理的,它會(huì)在合適的時(shí)間段進(jìn)行統(tǒng)一處理

所以 進(jìn)程信號(hào) 可以分為三步:信號(hào)產(chǎn)生 =》 信號(hào)保存 =》 信號(hào)處理

Linux進(jìn)程信號(hào)【信號(hào)產(chǎn)生】

本文講解的就是 信號(hào)產(chǎn)生 部分相關(guān)知識(shí),下面正式開始學(xué)習(xí) 信號(hào)產(chǎn)生


===== 信號(hào)產(chǎn)生的方式 =====

2、鍵盤鍵入

信號(hào)產(chǎn)生(發(fā)送)的第一種方式:鍵盤鍵入

通俗來說就是命令行操作

2.1、ctrl+c 終止前臺(tái)進(jìn)程

系統(tǒng)卡死遇到過吧?程序死循環(huán)遇到過吧?這些都是比較常見的問題,當(dāng)發(fā)生這些問題時(shí),我們可以通過 鍵盤鍵入 ctrl + c 發(fā)出 2 號(hào)信號(hào)終止前臺(tái)進(jìn)程的運(yùn)行

下面是一段死循環(huán)代碼:

#include <iostream>
#include <unistd.h>
using namespace std;

int main()
{
    while(true)
    {
        cout << "我是一個(gè)進(jìn)程,我正在運(yùn)行…… PID: " << getpid() << endl;
        sleep(1);
    }

    return 0;
}

運(yùn)行程序后,會(huì)一直循環(huán)打印,此時(shí)如果想要終止進(jìn)程,可以直接按 ctrl + c 發(fā)出 2 號(hào)信號(hào),終止前臺(tái)進(jìn)程

Linux進(jìn)程信號(hào)【信號(hào)產(chǎn)生】

此時(shí)發(fā)出了一個(gè) 2 號(hào)信號(hào) SIGINT 終止了該進(jìn)程的運(yùn)行

如何證明呢?如何證明按 ctrl + c 發(fā)出的是 2 號(hào)信號(hào)呢?

證明自有方法,前面說過,一個(gè)信號(hào)配有一個(gè)執(zhí)行動(dòng)作,并且執(zhí)行動(dòng)作是可以修改的,需要用到 signal 函數(shù)(屬于 信號(hào)處理 部分的內(nèi)容,這里需要提前用一下)

ctrl + c 終止的是當(dāng)前正在運(yùn)行的前臺(tái)進(jìn)程,如果在程序運(yùn)行時(shí)加上 & 表示讓其后臺(tái)運(yùn)行,此時(shí)會(huì)發(fā)現(xiàn)無(wú)法終止進(jìn)程

Linux進(jìn)程信號(hào)【信號(hào)產(chǎn)生】

像這種后臺(tái)進(jìn)程 ctrl + c 是無(wú)法終止的,可以通過 kill -9 PID 發(fā)出 9 信號(hào)終止它

2.1.1、signal 注冊(cè)執(zhí)行動(dòng)作

signal 函數(shù)可以用來 修改信號(hào)的執(zhí)行動(dòng)作,也叫注冊(cè)自定義執(zhí)行動(dòng)作

Linux進(jìn)程信號(hào)【信號(hào)產(chǎn)生】
signal 調(diào)用成功返回上一個(gè)執(zhí)行方法的值(其實(shí)就是下標(biāo),后面介紹),失敗則返回 SIG_ERR,并設(shè)置錯(cuò)誤碼

返回值可以不用關(guān)注,重點(diǎn)在于 signal 的參數(shù)

  • 參數(shù)1 待操作信號(hào)的編號(hào)
  • 參數(shù)2 待注冊(cè)的新方法

參數(shù)1 就是信號(hào)編號(hào),為 int,單純地傳遞 信號(hào)名也是可以的,因?yàn)樾盘?hào)名其實(shí)就是信號(hào)編號(hào)的宏定義

Linux進(jìn)程信號(hào)【信號(hào)產(chǎn)生】

參數(shù)2 是一個(gè)函數(shù)指針,意味著需要傳遞一個(gè) 參數(shù)為 int,返回值為空的函數(shù)對(duì)象

  • 參數(shù) int 是執(zhí)行動(dòng)作的信號(hào)編號(hào)
void handler(int)	//其中的函數(shù)名可以自定義

顯然,signal 函數(shù)是一個(gè) 回調(diào)函數(shù),當(dāng)信號(hào)發(fā)出時(shí),會(huì)去調(diào)用相應(yīng)的函數(shù),也就是執(zhí)行相應(yīng)的動(dòng)作

我們先對(duì) 2 號(hào)信號(hào)注冊(cè)新動(dòng)作,在嘗試按下 ctrl + c,看看它發(fā)出的究竟是不是 2 號(hào)信號(hào)

#include <iostream>
#include <signal.h>
#include <unistd.h>
using namespace std;

void handler(int signo)
{
    cout << "當(dāng)前 " << signo << " 號(hào)信號(hào)正在嘗試執(zhí)行相應(yīng)的動(dòng)作" << endl;
}

int main()
{

    //給 2 號(hào)信號(hào)注冊(cè)新方法
    signal(2, handler);

    while(true)
    {
        cout << "我是一個(gè)進(jìn)程,我正在運(yùn)行…… PID: " << getpid() << endl;
        sleep(1);
    }

    return 0;
}

Linux進(jìn)程信號(hào)【信號(hào)產(chǎn)生】

當(dāng)我們修改 2 號(hào)信號(hào)的執(zhí)行動(dòng)作后,再次按下 ctrl + c 嘗試終止前臺(tái)進(jìn)程,結(jié)果失敗了!執(zhí)行動(dòng)作變成了我們注冊(cè)的新動(dòng)作

這足以證明 ctrl + c 就是在給前臺(tái)進(jìn)程發(fā)出 2 號(hào)信號(hào),ctrl + c 失效后,可以通過 ctrl + \ 終止進(jìn)程,發(fā)出的是 3 號(hào)信號(hào)(3 號(hào)信號(hào)在發(fā)出后,會(huì)生成 核心轉(zhuǎn)儲(chǔ) 文件)

普通信號(hào)只有 31 個(gè),如果把所有普通信號(hào)的執(zhí)行動(dòng)作都改了,會(huì)發(fā)生什么呢?難道會(huì)得到一個(gè)有著 金剛不壞 之身的進(jìn)程嗎?

#include <iostream>
#include <signal.h>
#include <unistd.h>
using namespace std;

void handler(int signo)
{
    cout << "當(dāng)前 " << signo << " 號(hào)信號(hào)正在嘗試執(zhí)行相應(yīng)的動(dòng)作" << endl;
}

int main()
{

    //給所有普通信號(hào)注冊(cè)新方法

    for(int i = 1; i < 32; i++)
        signal(i, handler);

    while(true)
    {
        cout << "我是一個(gè)進(jìn)程,我正在運(yùn)行…… PID: " << getpid() << endl;
        sleep(1);
    }

    return 0;
}

Linux進(jìn)程信號(hào)【信號(hào)產(chǎn)生】

大部分信號(hào)的執(zhí)行動(dòng)作都被修改了,9 號(hào)信號(hào)沒有,因?yàn)?9 號(hào)信號(hào)是 SIGKILL,專門用于殺死進(jìn)程,只要是進(jìn)程,他都能干掉

19 號(hào)信號(hào) SIGSTOP 也無(wú)法修改執(zhí)行動(dòng)作,所以前面說過,9 號(hào) SIGKILL19 號(hào) SIGSTOP 信號(hào)是很特殊的,經(jīng)過特殊設(shè)計(jì),不能修改其執(zhí)行動(dòng)作!

2.2、硬件中斷

當(dāng)我們從鍵盤按下 ctrl + c 時(shí),發(fā)生了這些事:CPU 獲取到鍵盤 “按下” 的信號(hào),調(diào)用鍵盤相應(yīng)的 “方法” ,從鍵盤中讀取數(shù)據(jù),讀取數(shù)據(jù)后解析,然后發(fā)出 3 號(hào)信號(hào)

其中 CPU 捕獲鍵盤 “按下” 信號(hào)的操作稱為 硬件中斷

CPU 中有很多的針腳,不同的硬件對(duì)應(yīng)著不同的針腳,每一個(gè)針腳都有自己的編號(hào),硬件與針腳一對(duì)一相連,并通過 中斷控制器(比如 8259)進(jìn)行控制,當(dāng)我們按下鍵盤后

  • 中斷控制器首先給 CPU 發(fā)送信息,包括鍵盤對(duì)應(yīng)的針腳號(hào)
  • 然后 CPU 將獲取到的針腳號(hào)(中斷號(hào))寫入 寄存器 中
  • 最后根據(jù) 寄存器 里的 中斷號(hào),去 中斷向量表 中查表,找到對(duì)應(yīng)硬件的方法,執(zhí)行它的讀取方法就行了

這樣 CPU 就知道是 鍵盤 發(fā)出的信號(hào),然后就會(huì)去調(diào)用 鍵盤 的執(zhí)行方法,通過鍵盤的讀取方法,讀取到 ctrl + c 這個(gè)信息,轉(zhuǎn)化后,就是 2 號(hào)信號(hào),執(zhí)行終止前臺(tái)進(jìn)程的動(dòng)作

鍵盤被按下 和 鍵盤哪些位置被按下 是不一樣的

  • 首先鍵盤先按下,CPU 確定對(duì)應(yīng)的讀取方法
  • 其次才是通過 讀取方法 從鍵盤中讀取數(shù)據(jù)

注:鍵盤讀取方法如何進(jìn)行讀取,這是驅(qū)動(dòng)的事,我們不用關(guān)心

Linux進(jìn)程信號(hào)【信號(hào)產(chǎn)生】

硬件中斷 的流程與 進(jìn)程信號(hào) 的流程雷同,同樣是 先檢測(cè)到信號(hào),然后再去執(zhí)行相應(yīng)的動(dòng)作,不過此時(shí)發(fā)送的是 中斷信號(hào),執(zhí)行的是 調(diào)用相應(yīng)方法罷了

信號(hào) 與 動(dòng)作 的設(shè)計(jì)方式很實(shí)用,操作系統(tǒng)只需要關(guān)注是否有信號(hào)發(fā)出,發(fā)出后去中斷向量表中調(diào)用相應(yīng)的方法即可,不用管硬件是什么樣、如何變化,做到了 操作系統(tǒng) 與 硬件 間的解耦


3、系統(tǒng)調(diào)用

除了可以通過 鍵盤鍵入 發(fā)送信號(hào)外,還可以通過直接調(diào)用 系統(tǒng)接口 發(fā)送信號(hào),畢竟 bash 也是一個(gè)進(jìn)程,本質(zhì)上就是在進(jìn)行程序替換而已

3.1、kill 函數(shù)

信號(hào)的發(fā)送主要是通過 kill 函數(shù)進(jìn)行發(fā)送

Linux進(jìn)程信號(hào)【信號(hào)產(chǎn)生】
返回值:成功返回 0,失敗返回 -1 并設(shè)置錯(cuò)誤碼

參數(shù)1:待操作進(jìn)程的 PID

參數(shù)2:待發(fā)送的信號(hào)

下面來簡(jiǎn)單用一下(程序運(yùn)行 5 秒后,自己把自己殺死)

#include <iostream>
#include <signal.h>
#include <unistd.h>
using namespace std;

int main()
{

    int n = 1;
    while (true)
    {

        cout << "我是一個(gè)進(jìn)程,已經(jīng)運(yùn)行了 " << n << " 秒 PID: " << getpid() << endl;
        sleep(1);
        n++;

        if (n > 5)
            kill(getpid(), SIGKILL);
    }

    return 0;
}

Linux進(jìn)程信號(hào)【信號(hào)產(chǎn)生】

kill 函數(shù)當(dāng)然也可以發(fā)送其他信號(hào),這里就不一一展示了,其實(shí)命令行中的 kill 命令就是對(duì) kill 函數(shù)的封裝,kill -信號(hào)編號(hào) -PID 其中的參數(shù)2、3不正是 kill 函數(shù)所需要的參數(shù)嗎?所以我們可以嘗試自己搞一個(gè) myKill 命令

3.2、模擬實(shí)現(xiàn) myKill

這里就直接利用 命令行參數(shù) 簡(jiǎn)單實(shí)現(xiàn)了

#include <iostream>
#include <string>
#include <signal.h>

using namespace std;

void Usage(string proc)
{
    // 打印使用信息
    cout << "\tUsage: \n\t";
    cout << proc << " 信號(hào)編號(hào) 目標(biāo)進(jìn)程" << endl;
    exit(2);
}

int main(int argc, char *argv[])
{
    // 參數(shù)個(gè)數(shù)要嚴(yán)格限制
    if (argc != 3)
    {
        Usage(argv[0]);
    }

    //獲取兩個(gè)參數(shù)
    int signo = atoi(argv[1]);
    int pid = atoi(argv[2]);

    //執(zhí)行信號(hào)發(fā)送
    kill(pid, signo);

    return 0;
}

下面隨便跑一個(gè)進(jìn)程,然后用自己寫的 myKill 命令給進(jìn)程發(fā)信號(hào)

Linux進(jìn)程信號(hào)【信號(hào)產(chǎn)生】

我們可以把這個(gè)程序改造下,改成進(jìn)程替換的方式,讓后將自己寫的命令進(jìn)行安裝,就能像 kill 一樣直接使用了

3.3、raise 函數(shù)

發(fā)送信號(hào)的還有一個(gè) raise 函數(shù),這個(gè)函數(shù)比較奇怪,只能 自己給自己發(fā)信號(hào)

Linux進(jìn)程信號(hào)【信號(hào)產(chǎn)生】
返回值:成功返回 0,失敗返回 非0

就只有一個(gè)參數(shù):待發(fā)送的信號(hào)

可以這樣理解:raise 是對(duì) kill 函數(shù)的封裝,每次傳遞的都是自己的 PID

#include <iostream>
#include <signal.h>
#include <unistd.h>
using namespace std;

int main()
{
    int n = 1;
    while (true)
    {

        cout << "我是一個(gè)進(jìn)程,已經(jīng)運(yùn)行了 " << n << " 秒 PID: " << getpid() << endl;
        sleep(1);
        n++;

        if (n > 5)
            raise(SIGKILL); //自己殺死自己    
    }
	return 0;
}

Linux進(jìn)程信號(hào)【信號(hào)產(chǎn)生】

3.4、abort 函數(shù)

abortC 語(yǔ)言提供的一個(gè)函數(shù),它的作用是 給自己發(fā)送 6 號(hào) SIGABRT 信號(hào)

Linux進(jìn)程信號(hào)【信號(hào)產(chǎn)生】

沒有返回值,也沒有參數(shù)

值得一提的是,abort 函數(shù)即使在修改執(zhí)行動(dòng)作后,最后仍然會(huì)發(fā)送 6 號(hào)信號(hào)

#include <iostream>
#include <signal.h>
#include <unistd.h>
using namespace std;

void handler(int signo)
{
    cout << "收到了 " << signo << " 號(hào)信號(hào),已執(zhí)行新動(dòng)作" << endl;
}

int main()
{
    signal(6, handler);
    // signal(SIGABRT, handler);    //這種寫法也是可以的

    int n = 1;
    while (true)
    {

        cout << "我是一個(gè)進(jìn)程,已經(jīng)運(yùn)行了 " << n << " 秒 PID: " << getpid() << endl;
        sleep(1);
        n++;

        if (n > 5)
            abort();
    }
    return 0;
}

Linux進(jìn)程信號(hào)【信號(hào)產(chǎn)生】

即使執(zhí)行了我們新注冊(cè)的方法,abort 最后仍然會(huì)發(fā)出 6 號(hào)信號(hào)終止進(jìn)程

同樣是終止進(jìn)程,C語(yǔ)言 還提供了一個(gè)更好用的函數(shù):exit(),所以 abort 用的比較少,了解即可

總的來說,系統(tǒng)調(diào)用中舉例的這三個(gè)函數(shù)關(guān)系是:kill 包含 raise,raise 包含 abort,作用范圍是在逐漸縮小的

Linux進(jìn)程信號(hào)【信號(hào)產(chǎn)生】


4、軟件條件

信號(hào)產(chǎn)生(發(fā)送)的第三種方式:軟件條件

其實(shí)這種方式我們之前就接觸過了:管道讀寫時(shí),如果讀端關(guān)閉,那么操作系統(tǒng)會(huì)發(fā)送信號(hào)終止寫端,這個(gè)就是 軟件條件 引發(fā)的信號(hào)發(fā)送,發(fā)出的是 13 號(hào) SIGPIPE 信號(hào)

4.1、alarm 設(shè)置鬧鐘

系統(tǒng)為我們提供了 鬧鐘(報(bào)警):alarm,這個(gè) 鬧鐘 可不是用來起床的,而是用來 定時(shí)

Linux進(jìn)程信號(hào)【信號(hào)產(chǎn)生】

返回值:如果上一個(gè)鬧鐘還有剩余時(shí)間,則返回剩余時(shí)間,否則返回 0
參數(shù):想要設(shè)定的時(shí)間,單位是秒

當(dāng)時(shí)間到達(dá)鬧鐘中的預(yù)設(shè)時(shí)間時(shí),鬧鐘會(huì)響,并且發(fā)送 14 號(hào) SIGALRM 信號(hào)

比如這樣:

#include <iostream>
#include <signal.h>
#include <unistd.h>
using namespace std;

int main()
{

    alarm(5);   //設(shè)定一個(gè)五秒后的鬧鐘

    int n = 1;
    while (true)
    {

        cout << "我是一個(gè)進(jìn)程,已經(jīng)運(yùn)行了 " << n << " 秒 PID: " << getpid() << endl;
        sleep(1);
        n++;
    }
    return 0;
}

Linux進(jìn)程信號(hào)【信號(hào)產(chǎn)生】

我們也可以更改 14 號(hào) SIGALRM 信號(hào)的執(zhí)行動(dòng)作,讓鬧鐘不斷響起(自舉)

#include <iostream>
#include <signal.h>
#include <unistd.h>
using namespace std;

void handler(int signo)
{
    cout << "收到了 " << signo << " 號(hào)信號(hào),已執(zhí)行新動(dòng)作" << endl;
    int n = alarm(10);
    cout << "上一個(gè)鬧鐘剩余時(shí)間: " << n << endl;
}

int main()
{
    signal(SIGALRM, handler);
    alarm(10);   //設(shè)定一個(gè)十秒后的鬧鐘

    while(true)
    {
         cout << "我是一個(gè)進(jìn)程,我正在運(yùn)行…… PID: " << getpid() << endl;
         sleep(1);
    };

    return 0;
}

Linux進(jìn)程信號(hào)【信號(hào)產(chǎn)生】

系統(tǒng)中不止一個(gè)鬧鐘,所以 OS 需要 先描述,再組織,將這些鬧鐘管理起來

可以借助鬧鐘,簡(jiǎn)單測(cè)試一下當(dāng)前服務(wù)器的算力

4.2、測(cè)試算力

如何簡(jiǎn)單粗暴的測(cè)試算力? 設(shè)個(gè) 1 秒后響起的鬧鐘,看看程序能將一個(gè)值累加至多少

#include <iostream>
#include <signal.h>
#include <unistd.h>
using namespace std;

int main()
{
    alarm(1);   //設(shè)定一個(gè)一秒后的鬧鐘

    int n = 0;
    while(true)
    {
        cout << n++ << endl;
    };

    return 0;
}

Linux進(jìn)程信號(hào)【信號(hào)產(chǎn)生】

這個(gè)云服務(wù)這么拉嗎?只能累加幾萬(wàn)次

其實(shí)不是,主要是因?yàn)楫?dāng)前程序涉及了 IO,這是非常耗時(shí)間的,可以取消 IO 并修改 SIGALRM 的執(zhí)行動(dòng)作為打印變量,看看能累加多少次

#include <iostream>
#include <signal.h>
#include <unistd.h>
using namespace std;

int n = 0;

void handler(int signo)
{
    cout << n << endl;
    exit(1;
}

int main()
{
    signal(SIGALRM, handler);
    alarm(1);   //設(shè)定一個(gè)一秒后的鬧鐘

    while(true)
        n++;

    return 0;
}

Linux進(jìn)程信號(hào)【信號(hào)產(chǎn)生】

可以看到,取消 IO 后,累加了 5 億多次,近 10000 倍的差距

通過這個(gè)簡(jiǎn)單的小程序證明了一件事:IO 是非常慢的,能不 IO 就不 IO

注:因?yàn)楫?dāng)前是云服務(wù)器,存在 網(wǎng)絡(luò)延遲 的影響,所以實(shí)際差異更大

注意:鬧鐘是一次性的,只能響一次


5、硬件異常

最后一種產(chǎn)生(發(fā)送)信號(hào)的方式是:硬件異常

所謂 硬件異常 其實(shí)就是我們?cè)趯懗绦蜃畛S龅降母鞣N報(bào)錯(cuò),比如 除 0、野指針

5.1、除 0 導(dǎo)致異常

先來看一段簡(jiǎn)單的錯(cuò)誤代碼

#include <iostream>
using namespace std;

int main()
{
    int n = 10;
    n /= 0;

    return 0;
}

顯然是會(huì)報(bào)錯(cuò)的是,畢竟 0 不能作為常數(shù)

Linux進(jìn)程信號(hào)【信號(hào)產(chǎn)生】

根據(jù)報(bào)錯(cuò)信息,可以推測(cè)出此時(shí)發(fā)送的是 8 號(hào) SIGFPE 信號(hào)(浮點(diǎn)異常)

讓我們通過 signal 更改 8 號(hào)信號(hào)的執(zhí)行動(dòng)作,嘗試逆天改命,讓 除 0 合法?

#include <iostream>
#include <signal.h>
#include <unistd.h>
using namespace std;

void handler(int signo)
{
    cout << "雖然除 0 了,但我不終止進(jìn)程" << endl;
}

int main()
{
    signal(SIGFPE, handler);
    int n = 10;
    n /= 0;

    return 0;
}

Linux進(jìn)程信號(hào)【信號(hào)產(chǎn)生】

結(jié)果:一直在死循環(huán)似的發(fā)送信號(hào),明明只發(fā)生了一次 除 0 行為

想要明白背后的原理,需要先認(rèn)識(shí)一下 狀態(tài)寄存器

5.2、狀態(tài)寄存器

CPU 中,存在很多 寄存器,其中大部分主要用來存儲(chǔ)數(shù)據(jù)信息,用于運(yùn)算,除此之外,還存在一種特殊的 寄存器 =》 狀態(tài)寄存器,這個(gè) 寄存器 專門用來檢測(cè)當(dāng)前進(jìn)程是否出現(xiàn)錯(cuò)誤行為,如果有,就會(huì)把 狀態(tài)寄存器(位圖結(jié)構(gòu))中對(duì)應(yīng)的比特位置 1,意味著出現(xiàn)了 異常

當(dāng)操作系統(tǒng)檢測(cè)到 狀態(tài)寄存器 出現(xiàn)異常時(shí),會(huì)根據(jù)其中的值,向出現(xiàn)異常的進(jìn)程 輪詢式 的發(fā)送信號(hào),目的就是讓進(jìn)程退出

比如上面的 除 0 代碼,發(fā)生異常后,CPU狀態(tài)寄存器 修改,變成 異常狀態(tài),操作系統(tǒng)檢測(cè)到 異常 后會(huì)向進(jìn)程發(fā)送 8 號(hào)信號(hào),即使我們修改了 8 號(hào)信號(hào)的執(zhí)行動(dòng)作,但 因?yàn)闋顟B(tài)寄存器仍然處于異常狀態(tài),所以操作系統(tǒng)才會(huì)不斷發(fā)送 8 號(hào)信號(hào),所以才會(huì)死循環(huán)式的打印

Linux進(jìn)程信號(hào)【信號(hào)產(chǎn)生】

能讓 狀態(tài)寄存器 變?yōu)?異常 的都不是小問題,需要立即終止進(jìn)程,然后尋找、解決問題

畢竟如果讓 除 0 變?yōu)楹戏ǎ亲罱K的結(jié)果是多少呢?所以操作系統(tǒng)才會(huì)不斷發(fā)送信號(hào),目的就是 終止進(jìn)程的運(yùn)行

5.3、野指針導(dǎo)致異常

除了 除 0 異常外,還有一個(gè) 臭名昭著 的異常:野指針問題

比如:

#include <iostream>
using namespace std;

int main()
{
    int* ptr = nullptr;
    *ptr = 10;

    return 0;
}

Linux進(jìn)程信號(hào)【信號(hào)產(chǎn)生】
Segmentation fault 段錯(cuò)誤 這是每個(gè) C/C++ 程序猿都會(huì)遇到的問題,因?yàn)樘菀子|發(fā)了,出現(xiàn)段錯(cuò)誤問題時(shí),操作系統(tǒng)會(huì)發(fā)送 11 號(hào) SIGSEGV 信號(hào)終止進(jìn)程,可以通過修改執(zhí)行動(dòng)作驗(yàn)證,這里不再演示

那么 野指針 問題是如何引發(fā)的呢?

借用一下 共享內(nèi)存 中的圖~

Linux進(jìn)程信號(hào)【信號(hào)產(chǎn)生】

野指針問題主要分為兩類:

  1. 指向不該指向的空間
  2. 權(quán)限不匹配,比如只讀的區(qū)域,偏要去寫

共識(shí):在執(zhí)行 *ptr = 10 這句代碼時(shí),首先會(huì)進(jìn)行 虛擬地址 -> 真實(shí)(物理)地址 之間的轉(zhuǎn)換

指向不該指向的空間:這很好理解,就是頁(yè)表沒有將 這塊虛擬地址空間 與 真實(shí)(物理)地址空間 建立映射關(guān)系,此時(shí)進(jìn)行訪問時(shí) MMU 識(shí)別到異常,于是 MMU 直接報(bào)錯(cuò),操作系統(tǒng)識(shí)別到 MMU 異常后,向?qū)?yīng)的進(jìn)程發(fā)出終止信號(hào)

C語(yǔ)言中對(duì)于越界 讀 的檢查不夠嚴(yán)格,屬于抽查行為,因此野指針越界讀還不一定報(bào)錯(cuò),但越界寫是一定會(huì)報(bào)錯(cuò)的

權(quán)限不匹配:頁(yè)表中除了保存映射關(guān)系外,還會(huì)保存該區(qū)域的權(quán)限情況,比如 是否命中 / RW 等權(quán)限,當(dāng)發(fā)生操作與權(quán)限不匹配時(shí),比如 nullptr 只允許讀取,并不允許其他行為,此時(shí)解引用就會(huì)觸發(fā) MMU 異常,操作系統(tǒng)識(shí)別到后,同樣會(huì)對(duì)對(duì)應(yīng)的進(jìn)程發(fā)出終止信號(hào)

頁(yè)表中的屬性

  • 是否命中
  • RW 權(quán)限
  • UK 權(quán)限(不必關(guān)心)

Linux進(jìn)程信號(hào)【信號(hào)產(chǎn)生】

注:MMU 是內(nèi)存管理單元,主要負(fù)責(zé) 虛擬地址 與 物理地址 間的轉(zhuǎn)換工作,同時(shí)還會(huì)識(shí)別各種異常行為

一旦引發(fā)硬件層面的問題,操作系統(tǒng)會(huì)直接發(fā)信號(hào),立即終止進(jìn)程

到目前為止,我們學(xué)習(xí)了很多信號(hào),分別對(duì)應(yīng)著不同的情況,其中有些信號(hào)還反映了異常信息,所以將信號(hào)進(jìn)行細(xì)分,還是很有必要的


6、核心轉(zhuǎn)儲(chǔ)

Linux 中提供了一種系統(tǒng)級(jí)別的能力,當(dāng)一個(gè)進(jìn)程在出現(xiàn)異常的時(shí)候,OS 可以將該進(jìn)程在異常的時(shí)候,核心代碼部分進(jìn)行 核心轉(zhuǎn)儲(chǔ),將內(nèi)存中進(jìn)程的相關(guān)數(shù)據(jù),全部 dump 到磁盤中,一般會(huì)在當(dāng)前進(jìn)程的運(yùn)行目錄下,形成 core.pid 這樣的二進(jìn)制文件(核心轉(zhuǎn)儲(chǔ) 文件)

6.1、核心轉(zhuǎn)儲(chǔ)的概念

對(duì)于某些信號(hào)來說,當(dāng)終止進(jìn)程后,需要進(jìn)行 core dump,產(chǎn)生核心轉(zhuǎn)儲(chǔ)文件

比如:3號(hào) SIGQUIT、4號(hào) SIGILL、5號(hào) SIGTRAP、6號(hào) SIGABRT7號(hào) SIGBUS、8號(hào) SIGFPE11號(hào) SIGSEGV、24號(hào) SIGXCPU25號(hào) SIGXFSZ、31號(hào) SIGSYS 都是可以產(chǎn)生核心轉(zhuǎn)儲(chǔ)文件的

不同信號(hào)的動(dòng)作(Action

  • Trem -> 單純終止進(jìn)程
  • Core -> 先發(fā)生核心轉(zhuǎn)儲(chǔ),生成核心轉(zhuǎn)儲(chǔ)文件(前提是此功能已打開),再終止進(jìn)程

但在前面的學(xué)習(xí)中,我們用過 3、68、11 號(hào)信號(hào),都沒有發(fā)現(xiàn) 核心轉(zhuǎn)儲(chǔ) 文件啊

難道是我們的環(huán)境有問題嗎?

確實(shí),當(dāng)前環(huán)境確實(shí)有問題,因?yàn)樗?云服務(wù)器,而 云服務(wù)器 中默認(rèn)是關(guān)閉核心轉(zhuǎn)儲(chǔ)功能的

6.2、打開與關(guān)閉核心轉(zhuǎn)儲(chǔ)

通過指令 ulimit -a 查看當(dāng)前系統(tǒng)中的資源限制情況

ulimit -a

Linux進(jìn)程信號(hào)【信號(hào)產(chǎn)生】

可以看到,當(dāng)前系統(tǒng)中的核心轉(zhuǎn)儲(chǔ)文件大小為 0,即不生成核心轉(zhuǎn)儲(chǔ)文件

通過指令手動(dòng)設(shè)置核心轉(zhuǎn)儲(chǔ)文件大小

ulimit -c 1024

Linux進(jìn)程信號(hào)【信號(hào)產(chǎn)生】

現(xiàn)在可以生成核心轉(zhuǎn)儲(chǔ)文件了

就拿之前的 野指針 代碼測(cè)試,因?yàn)樗l(fā)送的是 11 號(hào)信號(hào),會(huì)產(chǎn)生 core dump 文件

Linux進(jìn)程信號(hào)【信號(hào)產(chǎn)生】

核心轉(zhuǎn)儲(chǔ)文件是很大的,而有很多信號(hào)都會(huì)產(chǎn)生核心轉(zhuǎn)儲(chǔ)文件,所以云服務(wù)器一般默認(rèn)是關(guān)閉的

云服務(wù)器上是可以部署服務(wù)的,一般程序發(fā)生錯(cuò)誤后,會(huì)立即重啟
如果打開了核心轉(zhuǎn)儲(chǔ),一旦程序 不斷掛掉、又不斷重啟,那么必然會(huì)產(chǎn)生大量的核心轉(zhuǎn)儲(chǔ)文件,當(dāng)文件足夠多時(shí),磁盤被擠滿,導(dǎo)致系統(tǒng) IO 異常,最終會(huì)導(dǎo)致整個(gè)服務(wù)器掛掉的
還有一個(gè)重要問題是 core 文件中可能包含用戶密碼等敏感信息,不安全

關(guān)閉核心轉(zhuǎn)儲(chǔ)很簡(jiǎn)單,設(shè)置為 0 就好了

ulimit -c 0

6.3、核心轉(zhuǎn)儲(chǔ)的作用

如此大的核心轉(zhuǎn)儲(chǔ)文件有什么用呢?

答案是 調(diào)試

沒錯(cuò),核心轉(zhuǎn)儲(chǔ)文件可以調(diào)試,并且直接從出錯(cuò)的地方開始調(diào)試

這種調(diào)試方式叫做 事后調(diào)試

調(diào)試方法:

  1. gcc / g++ 編譯時(shí)加上 -g 生成可調(diào)試文件
  2. 運(yùn)行程序,生成 core-dump 文件
  3. gdb 程序 進(jìn)入調(diào)試模式
  4. core-file core.file 利用核心轉(zhuǎn)儲(chǔ)文件,快速定位至出錯(cuò)的地方

Linux進(jìn)程信號(hào)【信號(hào)產(chǎn)生】

之前在 進(jìn)程創(chuàng)建、控制、等待 中,我們談到了 當(dāng)進(jìn)程異常退出時(shí)(被信號(hào)終止),不再設(shè)置退出碼,而是設(shè)置 core dump 位 及 終止信號(hào)

也就是說,父進(jìn)程可以借此判斷子進(jìn)程是否產(chǎn)生了 核心轉(zhuǎn)儲(chǔ) 文件

Linux進(jìn)程信號(hào)【信號(hào)產(chǎn)生】


??總結(jié)

以上就是本次關(guān)于 Linux進(jìn)程信號(hào)【信號(hào)產(chǎn)生】的全部?jī)?nèi)容了,作為進(jìn)程信號(hào)系列的開篇之作,包含了很多內(nèi)容,首先是對(duì)信號(hào)的產(chǎn)生、保存、處理相關(guān)概念進(jìn)行了學(xué)習(xí),然后針對(duì)信號(hào)產(chǎn)生,闡述了四種不同的方式,最后學(xué)習(xí)了核心轉(zhuǎn)儲(chǔ)的相關(guān)概念,掌握了一種特殊的調(diào)試方式


Linux進(jìn)程信號(hào)【信號(hào)產(chǎn)生】

相關(guān)文章推薦

Linux進(jìn)程間通信 ===== :>

【消息隊(duì)列、信號(hào)量】、【共享內(nèi)存】、【命名管道】、【匿名管道】

Linux基礎(chǔ)IO ===== :>

【軟硬鏈接與動(dòng)靜態(tài)庫(kù)】、【深入理解文件系統(tǒng)】、【模擬實(shí)現(xiàn)C語(yǔ)言文件流】、【重定向及緩沖區(qū)理解】、【文件理解與操作】

Linux進(jìn)程控制 ===== :>

【簡(jiǎn)易版bash】、【進(jìn)程程序替換】、【創(chuàng)建、終止、等待】

Linux進(jìn)程學(xué)習(xí) ===== :>

【進(jìn)程地址】、【環(huán)境變量】、【進(jìn)程狀態(tài)】、【基本認(rèn)知】

Linux基礎(chǔ) ===== :>

【gdb】、【git】、【gcc/g++】、【vim】、Linux 權(quán)限理解和學(xué)習(xí)、聽說Linux基礎(chǔ)指令很多?這里都幫你總結(jié)好了文章來源地址http://www.zghlxwxcb.cn/news/detail-500602.html

到了這里,關(guān)于Linux進(jìn)程信號(hào)【信號(hào)產(chǎn)生】的文章就介紹完了。如果您還想了解更多內(nèi)容,請(qǐng)?jiān)谟疑辖撬阉鱐OY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!

本文來自互聯(lián)網(wǎng)用戶投稿,該文觀點(diǎn)僅代表作者本人,不代表本站立場(chǎng)。本站僅提供信息存儲(chǔ)空間服務(wù),不擁有所有權(quán),不承擔(dān)相關(guān)法律責(zé)任。如若轉(zhuǎn)載,請(qǐng)注明出處: 如若內(nèi)容造成侵權(quán)/違法違規(guī)/事實(shí)不符,請(qǐng)點(diǎn)擊違法舉報(bào)進(jìn)行投訴反饋,一經(jīng)查實(shí),立即刪除!

領(lǐng)支付寶紅包贊助服務(wù)器費(fèi)用

相關(guān)文章

  • Linux入門之進(jìn)程信號(hào)|信號(hào)產(chǎn)生的方式

    Linux入門之進(jìn)程信號(hào)|信號(hào)產(chǎn)生的方式

    文章目錄 一、信號(hào)入門 1.linux信號(hào)的基本概念 2.使用kill -l 命令可以查看系統(tǒng)定義的信號(hào)列表 3.信號(hào)處理常見方式 二、產(chǎn)生信號(hào) 1.通過終端按鍵產(chǎn)生信號(hào) 2.通過調(diào)用系統(tǒng)函數(shù)向進(jìn)程發(fā)信號(hào) 3.由軟條件產(chǎn)生信號(hào) 4.硬件異常產(chǎn)生信號(hào) ??? 1. /0異常 ??? 2.模擬野指針 信號(hào)是進(jìn)程之

    2024年02月09日
    瀏覽(20)
  • 【Linux】第八講:Linux進(jìn)程信號(hào)詳解(一)_ 認(rèn)識(shí)信號(hào) | 產(chǎn)生信號(hào)

    【Linux】第八講:Linux進(jìn)程信號(hào)詳解(一)_ 認(rèn)識(shí)信號(hào) | 產(chǎn)生信號(hào)

    「前言」文章是關(guān)于Linux進(jìn)程信號(hào)方面的知識(shí),本文的內(nèi)容是Linux進(jìn)程信號(hào)第一講,講解會(huì)比較細(xì),下面開始! 「歸屬專欄」Linux系統(tǒng)編程 「主頁(yè)鏈接」個(gè)人主頁(yè) 「筆者」楓葉先生(fy) ?「楓葉先生有點(diǎn)文青病」「每篇一句」? 人生天地間,忽如遠(yuǎn)行客。 ——《樂府·青青陵上

    2023年04月25日
    瀏覽(24)
  • 【Linux】進(jìn)程信號(hào) --- 信號(hào)的產(chǎn)生 保存 捕捉遞達(dá)

    【Linux】進(jìn)程信號(hào) --- 信號(hào)的產(chǎn)生 保存 捕捉遞達(dá)

    被愛情困住的是傻子 1. 關(guān)于信號(hào)這個(gè)話題我們其實(shí)并不陌生,早在以前的時(shí)候,我們想要?dú)⑺滥硞€(gè)后臺(tái)進(jìn)程的時(shí)候,無(wú)法通過ctrl+c熱鍵終止進(jìn)程時(shí),我們就會(huì)通過kill -9的命令來殺死信號(hào)。 查看信號(hào)也比較簡(jiǎn)單,通過kill -l命令就可以查看信號(hào)的種類,雖然最大的信號(hào)編號(hào)是

    2023年04月23日
    瀏覽(22)
  • 【Linux】進(jìn)程信號(hào) -- 信號(hào)產(chǎn)生 | 系統(tǒng)調(diào)用、硬件、軟件的信號(hào)發(fā)送

    【Linux】進(jìn)程信號(hào) -- 信號(hào)產(chǎn)生 | 系統(tǒng)調(diào)用、硬件、軟件的信號(hào)發(fā)送

    kill -l 是一個(gè)在 Linux 和 Unix 系統(tǒng)中使用的命令,用于列出可用的信號(hào)列表。 在Linux和Unix系統(tǒng)中,進(jìn)程可以通過發(fā)送信號(hào)來與其他進(jìn)程或操作系統(tǒng)交互。kill 命令可以向指定的進(jìn)程發(fā)送一個(gè)特定的信號(hào),以便對(duì)其進(jìn)行控制,例如終止進(jìn)程或重新啟動(dòng)進(jìn)程等。 kill -l 命令會(huì)列出可

    2024年02月16日
    瀏覽(59)
  • 【探索Linux】—— 強(qiáng)大的命令行工具 P.16(進(jìn)程信號(hào) —— 信號(hào)產(chǎn)生 | 信號(hào)發(fā)送 | 核心轉(zhuǎn)儲(chǔ))

    【探索Linux】—— 強(qiáng)大的命令行工具 P.16(進(jìn)程信號(hào) —— 信號(hào)產(chǎn)生 | 信號(hào)發(fā)送 | 核心轉(zhuǎn)儲(chǔ))

    在現(xiàn)代社會(huì)中,信號(hào)無(wú)處不在。我們的生活充滿了各種各樣的信號(hào),它們指引著我們前進(jìn)的方向,使我們能夠了解周圍環(huán)境的變化。正如在計(jì)算機(jī)編程中一樣,Linux進(jìn)程信號(hào)也是一種重要的信號(hào),它們扮演著相似的角色。 想象一下,在繁忙的城市街道上行駛,交通信號(hào)燈是我

    2024年02月05日
    瀏覽(17)
  • 【Linux】進(jìn)程信號(hào)(完整版) --- 信號(hào)產(chǎn)生 信號(hào)保存 信號(hào)捕捉 可重入函數(shù) volatile SIGCHLD信號(hào)等

    【Linux】進(jìn)程信號(hào)(完整版) --- 信號(hào)產(chǎn)生 信號(hào)保存 信號(hào)捕捉 可重入函數(shù) volatile SIGCHLD信號(hào)等

    ?? 作者: 阿潤(rùn)菜菜 ?? 專欄: Linux系統(tǒng)編程 我們想要?dú)⑺滥硞€(gè)后臺(tái)進(jìn)程的時(shí)候,無(wú)法通過ctrl+c熱鍵終止進(jìn)程時(shí),我們就會(huì)通過kill -9的命令來殺死信號(hào)。 查看信號(hào)也比較簡(jiǎn)單,通過 kill -l 命令就可以查看所有信號(hào)的種類,雖然最大的信號(hào)編號(hào)是64,但實(shí)際上所有信號(hào)只有6

    2024年02月04日
    瀏覽(26)
  • 【Linux】進(jìn)程信號(hào)篇Ⅰ:信號(hào)的產(chǎn)生(signal、kill、raise、abort、alarm)、信號(hào)的保存(core dump)

    【Linux】進(jìn)程信號(hào)篇Ⅰ:信號(hào)的產(chǎn)生(signal、kill、raise、abort、alarm)、信號(hào)的保存(core dump)

    kill -l 可以查看所有信號(hào): 其中,前面的數(shù)字就是信號(hào),后面的大寫英文就是信號(hào)名稱,實(shí)際就是宏。 我們需要關(guān)注的是 1~31 號(hào)普通信號(hào),關(guān)注他們有沒有產(chǎn)生(可以用 0 或者 1 表示)。 所以,進(jìn)程的 pcb 中,需要對(duì)產(chǎn)生的信號(hào)先用 位圖 保存起來,再按照一定的順序去處理

    2024年01月25日
    瀏覽(31)
  • 【linux】信號(hào)——信號(hào)產(chǎn)生

    【linux】信號(hào)——信號(hào)產(chǎn)生

    自我名言 : 只有努力,才能追逐夢(mèng)想,只有努力,才不會(huì)欺騙自己。 喜歡的點(diǎn)贊,收藏,關(guān)注一下把! 首先說明一點(diǎn)信號(hào)不是信號(hào)量。不能把這兩個(gè)東西放在一起。 那信號(hào)講什么呢? 那信號(hào)是怎么回事,這里只能這樣說, 信號(hào)是針對(duì)進(jìn)行發(fā)送某種信號(hào)到來的一種機(jī)制,讓

    2024年02月05日
    瀏覽(19)
  • 【Linux】信號(hào)概念與信號(hào)產(chǎn)生

    【Linux】信號(hào)概念與信號(hào)產(chǎn)生

    生活中類似信號(hào)的概念也不少,例如上課鈴聲響,就是信號(hào)的發(fā)出,我們聽到上課鈴聲,就是接收到信號(hào),我們快速回到教室上課就是對(duì)信號(hào)做出處理。那么我們是怎么認(rèn)識(shí)這些信號(hào)的呢?那必定是有人教我們,然后我們記住了。而且我們不單單要認(rèn)識(shí)信號(hào),還要識(shí)別信號(hào),

    2024年02月19日
    瀏覽(18)
  • 【Linux從入門到精通】信號(hào)(初識(shí)信號(hào) & 信號(hào)的產(chǎn)生)

    【Linux從入門到精通】信號(hào)(初識(shí)信號(hào) & 信號(hào)的產(chǎn)生)

    ? ?? 本篇文章會(huì)對(duì)Linux下的信號(hào)進(jìn)行詳細(xì)解釋。主要內(nèi)容是 什么是信號(hào)、信號(hào)的產(chǎn)生、核心轉(zhuǎn)儲(chǔ)等問題 。希望本篇文章會(huì)對(duì)你有所幫助。 文章目錄 引入 一、初識(shí)信號(hào) 1、1 生活中的信號(hào) 1、2 Linux 下的信號(hào) 1、3 信號(hào)+進(jìn)程所得的初識(shí)結(jié)論 二、信號(hào)的產(chǎn)生 2、1?用戶通過終端輸

    2024年02月09日
    瀏覽(21)

覺得文章有用就打賞一下文章作者

支付寶掃一掃打賞

博客贊助

微信掃一掃打賞

請(qǐng)作者喝杯咖啡吧~博客贊助

支付寶掃一掃領(lǐng)取紅包,優(yōu)惠每天領(lǐng)

二維碼1

領(lǐng)取紅包

二維碼2

領(lǐng)紅包