最美情侣中文字幕电影,在线麻豆精品传媒,在线网站高清黄,久久黄色视频

歡迎光臨散文網(wǎng) 會(huì)員登陸 & 注冊(cè)

Linux fd 系列|信號(hào)編程(signal)竟能這樣做?漲姿勢(shì)了!

2022-04-12 13:54 作者:補(bǔ)給站Linux內(nèi)核  | 我要投稿



信號(hào)是什么?

Linux 操作系統(tǒng)

首先說(shuō),信號(hào)(signal)是什么?

  • 信號(hào)( signal )本質(zhì)是 Linux 進(jìn)程間通信的一種機(jī)制,也叫軟中斷信號(hào)。既然是通信機(jī)制,那么就是傳遞信息用的,信號(hào)傳遞的信息很簡(jiǎn)單,就是一個(gè)整數(shù),一般用于配合系統(tǒng)管理任務(wù),比如進(jìn)程的終結(jié)、恢復(fù)、熱加載等。

  • 信號(hào)都用整數(shù)常量表示,命名以 SIG 為前綴,比如 SIGINT( ctrl-c 觸發(fā)),SIGKILL( kill -9 觸發(fā) )。

信號(hào)一般怎么產(chǎn)生?

  1. 由內(nèi)核產(chǎn)生,比如內(nèi)存錯(cuò)誤,除 0 等錯(cuò)誤,內(nèi)核通過(guò)信號(hào)通知到相應(yīng)的進(jìn)程;

  2. 可以由其他進(jìn)程傳遞給目標(biāo)進(jìn)程,比如 kill 命令就是專(zhuān)門(mén)干這個(gè)事情的;

信號(hào)處理分為兩個(gè)階段:

  1. 發(fā)送階段:內(nèi)核將信號(hào)(signal)放到對(duì)應(yīng)的 pending 隊(duì)列中;

  2. 傳遞階段:也叫做處理階段,內(nèi)核將信號(hào)從 pending 隊(duì)列中取出來(lái),并且進(jìn)行處理,一般是調(diào)用相應(yīng)的回調(diào)函數(shù)(處理方式有三種:用戶(hù)定義、內(nèi)核默認(rèn)定義 SIG_DEL、忽略 SIG_IGN);

signalfd 是什么?

  • 了解了什么是信號(hào)( signal ),那 signalfd 又會(huì)是什么呢?

  • 是一個(gè)跟信號(hào)關(guān)聯(lián)的文件描述符,能夠以 io 的行為獲取到系統(tǒng)信號(hào),屬性上來(lái)講 signalfd 也是一個(gè)匿名 fd 類(lèi)型。

signalfd 長(zhǎng)什么樣子?

  • 奇伢按照 man signalfd 里面的例子,寫(xiě)了個(gè) demo,跑在 Linux 機(jī)器上,按照慣例去看下 fd 的樣子。

  • 從這里可以得到簡(jiǎn)單的信息:

  1. signal 用的匿名 inode ,signalfd 屬于匿名 fd 的一種;

  2. 句柄關(guān)聯(lián)的重要信息就是 sigmask,通過(guò) /proc/${pid}/fdinfo/3 能看到這個(gè)值;


【文章福利】小編推薦自己的Linux內(nèi)核技術(shù)交流群:【891587639】整理了一些個(gè)人覺(jué)得比較好的學(xué)習(xí)書(shū)籍、視頻資料共享在群文件里面,有需要的可以自行添加哦?。?!前100名進(jìn)群領(lǐng)取,額外贈(zèng)送一份價(jià)值699的內(nèi)核資料包(含視頻教程、電子書(shū)、實(shí)戰(zhàn)項(xiàng)目及代碼)?



signalfd 使用姿勢(shì)?

  • 其實(shí)信號(hào)是很講究的,甚至有信號(hào)編程一說(shuō),Linux 的 signalfd 為信號(hào)的處理提供了一種新的方法,統(tǒng)一到文件的 io 模式,契合一切接文件的理念。

  • 系統(tǒng)調(diào)用:

  • 該系統(tǒng)調(diào)用返回一個(gè)整數(shù)類(lèi)型 signalfd,這個(gè)句柄跟信號(hào)行為綁定,當(dāng)發(fā)生信號(hào)的時(shí)候,句柄觸發(fā)可讀事件。

  • 第一個(gè)參數(shù)也可以傳入一個(gè)有效的信號(hào) fd 的句柄,如果傳入的是 -1 ,那么內(nèi)核會(huì)自動(dòng)創(chuàng)建一個(gè)新的 fd 。

  • 完整的代碼例子,在 Linux 機(jī)器上,通過(guò) man signalfd 就可以獲取到。

  • 上面的例子,signalfd 沒(méi)有信號(hào)(沒(méi)有可讀事件)的時(shí)候會(huì)阻塞在read調(diào)用上,運(yùn)行效果如下:

  • 可以看到每一次 ctrl + c 觸發(fā)的信號(hào)被捕捉到,并且打印出來(lái)。用文件 io 的方式來(lái)接收信號(hào),牛。

  • 怎么做到的呢?照例,我們淺析一下內(nèi)核的代碼,位于 fs/signalfd.c,這是一個(gè)很小的文件,正是這個(gè)文件完成了對(duì)信號(hào)“文件化”的封裝。


  • 上面最重要的兩個(gè)調(diào)用:

  1. sigprocmask :設(shè)置當(dāng)前進(jìn)程的信號(hào)掩碼,把 SIGINT,SIGQUIT 處理屏蔽掉,關(guān)閉內(nèi)核默認(rèn)行為;

  2. signalfd :獲取到一個(gè)和信號(hào)關(guān)聯(lián)的“文件”句柄;

signalfd 原理剖析

環(huán)境聲明:

Linux 內(nèi)核版本 4.19

1、signalfd

看一下 signalfd 支持的接口調(diào)用:

  • 通過(guò)這個(gè)可以知道 signalfd 支持的特性:

  1. 支持 /proc/${pid}/fdinfo/xx 查看信息( 對(duì)應(yīng) signalfd_show_fdinfo 函數(shù) );

  2. 支持 read,close 調(diào)用 ( 對(duì)應(yīng) signalfd_read 函數(shù) );

  3. 支持 poll 調(diào)用,支持 epoll 管理( 對(duì)應(yīng) signalfd_poll 函數(shù) );


2、signalfd_poll


  • 這個(gè)函數(shù)做的事情非常簡(jiǎn)單,就是把等待對(duì)象掛到當(dāng)前進(jìn)程的信號(hào)結(jié)構(gòu)的鏈表上。表頭是:current->sighand->signalfd_wqh ,這個(gè)就有意思了,這里直接掛到當(dāng)前進(jìn)程的結(jié)構(gòu)上。換句話(huà)說(shuō),喚醒也是自此表頭開(kāi)始。

  • 回憶一下 timerfd ,是掛在 timerfd_ctx->wqh 的字段上。這里的差別是因?yàn)樾盘?hào)是對(duì)進(jìn)程來(lái)說(shuō)的。


3、signalfd_read

  • 讀一個(gè) signalfd 的操作非常簡(jiǎn)單,主要邏輯:

  1. 查看當(dāng)前隊(duì)列中是否有信號(hào),有的話(huà)就取出來(lái),填充到用戶(hù)給的結(jié)構(gòu)體中;

  2. 如果句柄是阻塞類(lèi)型的,在沒(méi)有信號(hào)的時(shí)候,會(huì)切走 cpu,等到有信號(hào)的時(shí)候切回來(lái)。如果是非阻塞類(lèi)型的,直接報(bào)錯(cuò),返回 EAGAIN ;

  • 簡(jiǎn)要的代碼注釋如下:

  • 這里就能非常清晰的看到,進(jìn)程有信號(hào)的時(shí)候,signalfd 句柄就是可讀的。


signal 和 epoll 的配合

1、熟悉的 epoll_ctl


  • epoll_ctl 注冊(cè) signalfd 的時(shí)候,調(diào)用 signalfd_poll ,signalfd_poll 會(huì)把 epoll 創(chuàng)建的 wait entry 掛到 current->sighand 上。喚醒的時(shí)候調(diào)用這個(gè) wait 鏈表的回調(diào)。

2、什么時(shí)候喚醒呢?

  • 喚醒的操作其實(shí)不在 signalfd.c 文件中,而是在原有的信號(hào)軟中斷的流程中。

  • 在內(nèi)核函數(shù) signalfd_notify ?中,會(huì)判斷進(jìn)程的 sighand->signalfd_wqh 是否非空,如果非空,說(shuō)明有人關(guān)注這個(gè)信號(hào),那么就會(huì)通知到對(duì)應(yīng)的 waiter 。

  • 為了知識(shí)的完整性,說(shuō)個(gè)點(diǎn),signalfd_notify 其實(shí)在 timer 定時(shí)器的流程中也有調(diào)用,但跟我們本次主干沒(méi)啥關(guān)系,這里忽略。

  • 信號(hào)的發(fā)送喚醒的簡(jiǎn)要示意圖:

  • 所有的信號(hào)發(fā)送都會(huì)調(diào)用到send_signal,在這個(gè)里面實(shí)現(xiàn)了喚醒sighand->signalfd_wqh鏈表的操作。從而使得 epoll 感知到 signalfd 可讀了(因?yàn)閬?lái)信號(hào)了),使得 epoll 從 epoll_wait 出喚醒,然后調(diào)用 read 操作,把信號(hào)的相關(guān)信息從句柄中讀出來(lái)。

  • 劃重點(diǎn):?jiǎn)拘言谛盘?hào)發(fā)送的過(guò)程。

  • 總結(jié)

  • 信號(hào)能夠像文件一樣 read 出來(lái),這種優(yōu)雅的信號(hào)處理方式得益于 signalfd 的封裝;

  • 信號(hào)是掛在在進(jìn)程 task_struct 結(jié)構(gòu)體上的,信號(hào)隊(duì)列非空的時(shí)候 signalfd 句柄可讀;

  • 和 epoll 池的配合同樣還是老套路,epoll_ctl 注冊(cè)的時(shí)候調(diào)用 .poll ?接口掛載 epoll 的 wait entry 到 sighand->signalfd_wqh 之上,信號(hào)發(fā)送時(shí)調(diào)用 signalfd_notify ?喚醒 epoll ;

  • signalfd 也是一種匿名 fd 類(lèi)型;


Linux fd 系列|信號(hào)編程(signal)竟能這樣做?漲姿勢(shì)了!的評(píng)論 (共 條)

分享到微博請(qǐng)遵守國(guó)家法律
军事| 马山县| 霸州市| 邯郸市| 绥阳县| 荃湾区| 商南县| 竹北市| 镇沅| 玛沁县| 渭源县| 油尖旺区| 宜章县| 象州县| 浠水县| 长丰县| 吉隆县| 通海县| 淮滨县| 木兰县| 吉安县| 获嘉县| 锡林郭勒盟| 东安县| 德惠市| 米林县| 鄂州市| 四子王旗| 清水县| 新田县| 施秉县| 哈尔滨市| 林甸县| 泰兴市| 乌兰浩特市| 普兰县| 晋江市| 文安县| 寻乌县| 偏关县| 烟台市|