IPC方法-信號(hào)

信號(hào)通過(guò)軟件方法實(shí)現(xiàn)(軟中斷), 會(huì)導(dǎo)致延時(shí)性. 每個(gè)進(jìn)程接收到的信號(hào)都是由內(nèi)核發(fā)送處理的, 內(nèi)核作為中轉(zhuǎn).

未決: 產(chǎn)生和遞達(dá)之間的狀態(tài), 主要由于阻塞(屏蔽)導(dǎo)致.

未決信號(hào)集和阻塞信號(hào)集(信號(hào)屏蔽字)都存放在PCB中, 數(shù)據(jù)結(jié)構(gòu)是集合, 不重復(fù)但無(wú)序, 內(nèi)部存放0/1值. 正常傳遞時(shí), 未決信號(hào)集中從0變到1(未決)再?gòu)?變到0(被處理)的過(guò)程可以看作是瞬時(shí)的. 但當(dāng)阻塞信號(hào)集某編號(hào)因?yàn)槟撤N原因?yàn)?時(shí), 當(dāng)內(nèi)核發(fā)送信號(hào)后, 未決信號(hào)集中對(duì)應(yīng)的該編號(hào)也會(huì)變?yōu)?(不發(fā)送就仍為0), 所以說(shuō)阻塞信號(hào)集影響未決信號(hào)集.

信號(hào)的處理方式:
  1. 執(zhí)行默認(rèn)動(dòng)作
  2. 忽略(丟棄), 也是一種處理
  3. 捕捉, 調(diào)用戶處理函數(shù).
信號(hào)四要素:
  1. 名字 2. 編號(hào) 3. 默認(rèn)動(dòng)作 4. 對(duì)應(yīng)觸發(fā)事件
默認(rèn)動(dòng)作有5種:
  1. Term,終止進(jìn)程
  2. Core,終止進(jìn)程并產(chǎn)生core文件
  3. Ign,忽略
  4. Stop,暫停
  5. Cont,繼續(xù)

man 7 signal查看信號(hào), 當(dāng)一個(gè)名字對(duì)應(yīng)多個(gè)編號(hào)時(shí), 取中間那列的, 左右兩列為其他平臺(tái)的編號(hào).
9)SIGKILL和19)SIGSTOP比較特殊, 不允許忽略和捕捉, 甚至不允許阻塞, 只能執(zhí)行默認(rèn)動(dòng)作

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

1. 終端按鍵產(chǎn)生信號(hào)

ctrl + c 2)SIGINT 中斷信號(hào)interrupt, 終止進(jìn)程(Term)
ctrl + z 20)SIGTSTP 暫停與終端交互進(jìn)程, 放到后臺(tái)(Stop). 注意與19)SIGSTOP區(qū)分, SIGSTOP可以暫停任何進(jìn)程(Stop).
ctrl + \ 3)SIGQUIT 退出進(jìn)程(Core)

2. 硬件異常產(chǎn)生信號(hào)

除0操作 8)SIGFPE(浮點(diǎn)數(shù)例外)
非法訪問(wèn)內(nèi)存 11)SIGSEGV(段錯(cuò)誤)
總線錯(cuò)誤 7)SIGBUS

3. kill命令/函數(shù)產(chǎn)生信號(hào)

int kill(pid_t pid, int sig)可以調(diào)用kill函數(shù)
對(duì)于管道連接的進(jìn)程, 當(dāng)寫端進(jìn)程終止后, 寫端都關(guān)閉, 讀端也會(huì)跟著關(guān)閉, 所以只kill寫端進(jìn)程就會(huì)把管道兩端的進(jìn)程都?xì)⑺?

4. 自身調(diào)用raise()和abort()函數(shù)產(chǎn)生信號(hào)

5. 軟件條件產(chǎn)生信號(hào):alarm()和setitimer()

alarm()傳新的時(shí)間進(jìn)去后會(huì)覆蓋舊的, 所以返回的上一次剩下的秒數(shù)沒(méi)什么用, 如果alarm(0)就是關(guān)閉定時(shí)器, 直接終止進(jìn)程. 注意終止進(jìn)程只是默認(rèn)行為, 可以設(shè)置一個(gè)handler函數(shù)如signal(SIGALRM, handler)來(lái)注冊(cè)信號(hào)的捕捉函數(shù)(真正捕捉信號(hào)的是內(nèi)核), 這樣就可以在時(shí)間到了之后不終止進(jìn)程. 信號(hào)捕捉函數(shù)是一個(gè)典型的回調(diào)函數(shù)(封裝了一個(gè)函數(shù), 但是沒(méi)有直接調(diào)用).

可以使用time命令查看程序運(yùn)行的時(shí)間, 總時(shí)間=用戶空間時(shí)間+內(nèi)核空間時(shí)間+等待時(shí)間, 等待時(shí)間I/O占了大部分.

new_value是傳入?yún)?shù), 表示要定時(shí)的時(shí)間; old_value是傳出參數(shù), 表示上次剩的時(shí)間, 相當(dāng)于alarm()函數(shù)的返回值. setitimer成功返回0, 失敗返回-1.
需要先把結(jié)構(gòu)體成員賦初值, 再把結(jié)構(gòu)體指針傳到函數(shù)里, 分別指定val和interval的秒值/毫秒值:

signal(SIGALRM, signalHandler);

struct itimerval new_value, old_value;
new_value.it_value.tv_sec = 5;
new_value.it_value.tv_usec = 0;
new_value.it_interval.tv_sec = 3;
new_value.it_interval.tv_usec = 0;
setitimer(ITIMER_REAL, &new_value, &old_value);

只有第一次設(shè)定鬧鐘后5秒會(huì)接收到SIGALRM信號(hào), 之后每3秒接收到一個(gè)SIGALRM信號(hào).

信號(hào)集操作函數(shù)

sigset_t myset;自己的信號(hào)集, 即"位圖"

影響阻塞信號(hào)集3號(hào)位的方法:
1.先sigemptyset(&myset)sigaddset(&myset, 3)把自己的信號(hào)集3號(hào)位設(shè)置為1(注意信號(hào)集編號(hào)從1開始, 長(zhǎng)度為64位unsigned long int, 對(duì)應(yīng)kill -l列出來(lái)的信號(hào)宏, 一般操作前31個(gè)).
2.如果是設(shè)置阻塞, 調(diào)用sigprocmask(SIG_BLOCK, &myset, &oldset)把阻塞集mask的3號(hào)位置為1, 其中sigset_t oldset是傳出參數(shù), 用來(lái)保存原來(lái)的阻塞集狀態(tài), 可以傳NULL. 之后當(dāng)內(nèi)核發(fā)送3號(hào)信號(hào)(SIGQUIT)時(shí), 未決信號(hào)集的第3位也根據(jù)阻塞集變?yōu)?.
3.如果是解除阻塞, 調(diào)用sigprocmask(SIG_UNBLOCK, &myset, &oldset)把阻塞集mask的3號(hào)位置為0, 則未決集的3號(hào)位也會(huì)從1變0. 也就是說(shuō)無(wú)論是設(shè)置阻塞還是解除阻塞, 位圖myset的對(duì)應(yīng)號(hào)位都要置為1.

類似sigaddset()的的還有sigfillset(&myset)全置1, sigdelset(&myset, 3)把3號(hào)位改為0(若已為0則無(wú)動(dòng)作), sigismember(&myset, 5)判斷5號(hào)位是否為1.

阻塞信號(hào)集不可讀, 但可以使用int sigpending(sigset_t *set)來(lái)讀取未決信號(hào)集, set是傳出參數(shù). 打印信號(hào)集要使用sigismember函數(shù).

sigaction()捕捉信號(hào)

信號(hào)捕捉函數(shù)由內(nèi)核調(diào)用, 即所謂的回調(diào)模式, 只有在確認(rèn)信號(hào)已抵達(dá)后才會(huì)被調(diào)用, 在用戶空間執(zhí)行, 執(zhí)行完通過(guò)sigreturn返回內(nèi)核進(jìn)行報(bào)道, 再?gòu)纳洗伪恢袛嗟牡胤嚼^續(xù)執(zhí)行.

注冊(cè)信號(hào)捕捉函數(shù)除了signal(signum, handler)之外, 還可以使用int sigaction(int signum, const struct sigaction *act, struct sigaction *oldact)函數(shù), 用結(jié)構(gòu)體的sigset_t sa_mask成員設(shè)置信號(hào)處理期間要被屏蔽的信號(hào)集合(使用sigemptyset()和sigaddset()設(shè)置), 防止調(diào)用sa_handler(函數(shù)指針型成員變量)期間被打斷, sa_mask會(huì)覆蓋內(nèi)核的阻塞集mask. 另外sa_flags也要設(shè)置為0, 表示sa_handler處理某信號(hào)期間忽略相同信號(hào).
捕獲完信號(hào)后最好恢復(fù)成信號(hào)的默認(rèn)動(dòng)作sigaction(signum, &oldact, NULL), 且sigaction()調(diào)用前后都要對(duì)要接收的信號(hào)進(jìn)行屏蔽(設(shè)置mask), 以防止注冊(cè)信號(hào)捕捉函數(shù)的過(guò)程中信號(hào)到來(lái).

時(shí)序競(jìng)態(tài)(競(jìng)態(tài)條件)

pause()函數(shù)可以讓進(jìn)程主動(dòng)被掛起, 當(dāng)捕獲并處理完信號(hào)后返回-1, 設(shè)置errno為EINTR. 需和信號(hào)捕捉函數(shù)配合使用
如果alarm()后失去CPU, 且過(guò)了定時(shí)的時(shí)間, 當(dāng)重獲CPU時(shí)會(huì)先處理已發(fā)送并阻塞的SIGALRM信號(hào), 這樣pause()后就無(wú)法接收到本應(yīng)等待的SIGALRM, 從而一直掛起, 導(dǎo)致時(shí)序競(jìng)態(tài)問(wèn)題. 使用sigsuspend可解決該問(wèn)題.

sigsuspend()函數(shù)實(shí)質(zhì)上就是在內(nèi)核阻塞信號(hào)集mask上把SIGALRM屏蔽, 當(dāng)執(zhí)行sigsuspend()時(shí)再使用臨時(shí)阻塞集解除屏蔽. 這樣即使alarm后失去CPU, SIGALRM信號(hào)被阻塞, 等恢復(fù)執(zhí)行后也是先調(diào)用sigsuspend()并用捕捉函數(shù)處理信號(hào), 而不是先處理SIGALRM再pause()導(dǎo)致一直掛起.

全局變量異步I/O

對(duì)于進(jìn)程間通信, 全局變量存在異步I/O的情況, 應(yīng)盡量少用全局變量(使用鎖的機(jī)制可以避免這種情況). 即可能主函數(shù)信號(hào)發(fā)出后失去CPU, 當(dāng)恢復(fù)CPU后, 另一端已發(fā)送的信號(hào)會(huì)優(yōu)先被處理(信號(hào)捕捉函數(shù)里可以改變?nèi)肿兞?, 使得對(duì)全局變量的修改順序出現(xiàn)錯(cuò)誤, 導(dǎo)致進(jìn)程掛起.

使用全局變量的函數(shù)容易變成不可重入函數(shù), 一旦被信號(hào)打斷容易發(fā)生錯(cuò)誤, 執(zhí)行結(jié)果會(huì)和預(yù)期的不同(如遞歸操作). 所以信號(hào)捕捉函數(shù)要設(shè)計(jì)成可重入函數(shù), 避免使用全局變量和static變量, 避免使用malloc/free.

捕捉SIGCHLD回收子進(jìn)程

當(dāng)多個(gè)子進(jìn)程同時(shí)死亡時(shí), 雖然信號(hào)捕捉函數(shù)一次只能處理一個(gè)信號(hào), 但如果waitpid()第一個(gè)參數(shù)設(shè)為回收全部子進(jìn)程, 在這一次調(diào)用的過(guò)程中waitpid()就會(huì)把當(dāng)前剩下死亡的子進(jìn)程都回收掉, 此處信號(hào)的作用只是激活waitpid()函數(shù), 回收幾個(gè)子進(jìn)程由waitpid自己決定.

中斷慢速系統(tǒng)調(diào)用

read在讀文件時(shí)不會(huì)阻塞, 在讀網(wǎng)絡(luò)/設(shè)備/管道時(shí)可能發(fā)生阻塞, 此時(shí)收到信號(hào)就會(huì)被中斷.

中斷的慢速系統(tǒng)調(diào)用要么重啟要么執(zhí)行默認(rèn)動(dòng)作, 如果重啟需要again和goto參數(shù), 同時(shí)判斷EINTR信號(hào)

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末欲间,一起剝皮案震驚了整個(gè)濱河市闹究,隨后出現(xiàn)的幾起案子蚣驼,更是在濱河造成了極大的恐慌鄙煤,老刑警劉巖,帶你破解...
    沈念sama閱讀 221,576評(píng)論 6 515
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件请垛,死亡現(xiàn)場(chǎng)離奇詭異顾复,居然都是意外死亡,警方通過(guò)查閱死者的電腦和手機(jī)衷模,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 94,515評(píng)論 3 399
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)蒲赂,“玉大人阱冶,你說(shuō)我怎么就攤上這事±淖欤” “怎么了木蹬?”我有些...
    開封第一講書人閱讀 168,017評(píng)論 0 360
  • 文/不壞的土叔 我叫張陵,是天一觀的道長(zhǎng)若皱。 經(jīng)常有香客問(wèn)我镊叁,道長(zhǎng),這世上最難降的妖魔是什么走触? 我笑而不...
    開封第一講書人閱讀 59,626評(píng)論 1 296
  • 正文 為了忘掉前任晦譬,我火速辦了婚禮,結(jié)果婚禮上互广,老公的妹妹穿的比我還像新娘敛腌。我一直安慰自己卧土,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 68,625評(píng)論 6 397
  • 文/花漫 我一把揭開白布像樊。 她就那樣靜靜地躺著尤莺,像睡著了一般。 火紅的嫁衣襯著肌膚如雪生棍。 梳的紋絲不亂的頭發(fā)上颤霎,一...
    開封第一講書人閱讀 52,255評(píng)論 1 308
  • 那天,我揣著相機(jī)與錄音足绅,去河邊找鬼捷绑。 笑死,一個(gè)胖子當(dāng)著我的面吹牛氢妈,可吹牛的內(nèi)容都是我干的粹污。 我是一名探鬼主播,決...
    沈念sama閱讀 40,825評(píng)論 3 421
  • 文/蒼蘭香墨 我猛地睜開眼首量,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼壮吩!你這毒婦竟也來(lái)了?” 一聲冷哼從身側(cè)響起加缘,我...
    開封第一講書人閱讀 39,729評(píng)論 0 276
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤鸭叙,失蹤者是張志新(化名)和其女友劉穎,沒(méi)想到半個(gè)月后拣宏,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體沈贝,經(jīng)...
    沈念sama閱讀 46,271評(píng)論 1 320
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 38,363評(píng)論 3 340
  • 正文 我和宋清朗相戀三年勋乾,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了宋下。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 40,498評(píng)論 1 352
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡辑莫,死狀恐怖学歧,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情各吨,我是刑警寧澤枝笨,帶...
    沈念sama閱讀 36,183評(píng)論 5 350
  • 正文 年R本政府宣布,位于F島的核電站揭蜒,受9級(jí)特大地震影響横浑,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜屉更,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,867評(píng)論 3 333
  • 文/蒙蒙 一伪嫁、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧偶垮,春花似錦、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,338評(píng)論 0 24
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)。三九已至砚哗,卻和暖如春龙助,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背蛛芥。 一陣腳步聲響...
    開封第一講書人閱讀 33,458評(píng)論 1 272
  • 我被黑心中介騙來(lái)泰國(guó)打工提鸟, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人仅淑。 一個(gè)月前我還...
    沈念sama閱讀 48,906評(píng)論 3 376
  • 正文 我出身青樓称勋,卻偏偏與公主長(zhǎng)得像,于是被迫代替她去往敵國(guó)和親涯竟。 傳聞我的和親對(duì)象是個(gè)殘疾皇子赡鲜,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,507評(píng)論 2 359

推薦閱讀更多精彩內(nèi)容

  • 信號(hào)(signal)是一種軟件中斷银酬,它提供了一種處理異步事件的方法,也是進(jìn)程間惟一的異步通信方式筐钟。在Linux系統(tǒng)...
    夏大王2019閱讀 1,006評(píng)論 0 1
  • 一揩瞪、信號(hào)及信號(hào)來(lái)源 信號(hào)本質(zhì) 信號(hào)是在軟件層次上對(duì)中斷機(jī)制的一種模擬,在原理上篓冲,一個(gè)進(jìn)程收到一個(gè)信號(hào)與處理器收到一...
    丶Em1tu0F閱讀 1,442評(píng)論 0 1
  • 對(duì)于 Linux來(lái)說(shuō)李破,實(shí)際信號(hào)是軟中斷,許多重要的程序都需要處理信號(hào)纹因。信號(hào)喷屋,為 Linux 提供了一種處理異步事件...
    故事狗閱讀 85,057評(píng)論 2 62
  • 使用場(chǎng)景:1、為了并發(fā)瞭恰,中斷處理其它事件屯曹,1、進(jìn)程間通信1惊畏、中斷中止(注意不是終止)當(dāng)前正在執(zhí)行的程序恶耽,轉(zhuǎn)而執(zhí)行其...
    奧斯特洛司機(jī)閱讀 699評(píng)論 0 0
  • 轉(zhuǎn)自:http://www.dbafree.net/?p=870 我們可以使用kill -l查看所有的信號(hào)量解釋,...
    AndreaArlex閱讀 6,143評(píng)論 0 4