坑人的“殺手”組織
我是一個進(jìn)程,一出生就被塞了一張長長的任務(wù)單,上面是密密麻麻的任務(wù)指令,像什么 mv 了, cp 了, while 了..... 我一個都看不懂。
人類程序員告訴我這叫 shell 腳本,我的任務(wù)就是跑跑腿,到 shell 大街上找到能夠執(zhí)行這些指令的人,讓他們?nèi)?zhí)行。
這個活兒聽起來并不復(fù)雜,我按照人類的指示,進(jìn)入了 shell 大街。
初試身手
shell 大街上熱鬧非凡,各種進(jìn)程來來往往,兩旁的街道是大大小小、形形色色的門店,我左看右看,眼睛都不夠使了。
比如我旁邊這家店,招牌巨大,上面寫著 【我們不生產(chǎn)文件,我們只是文件系統(tǒng)的搬運工】,這是 “mv” 旗艦店。還有街口這家店,招牌也氣勢非凡:【你負(fù)責(zé)從 0 到 1,我搞定 1 到 100】,原來這家店專門負(fù)責(zé)抄錄備份文件,叫做 cp ,也是旗艦店。
我從懷里掏出任務(wù)單,看看我要干的活, 我希望指令是 mv 或者 cp,這樣我就可以去逛逛旁邊這兩家旗艦店了。
可是,第一條指令是 “pidof xyz”, 我環(huán)顧四周,怎么在 shell 大街上看不到 pidof 店鋪?
這時候街上的大喇叭響了:進(jìn)程管理局將于 4:30 下班,需要查詢進(jìn)程id的速速前往 shell 大街 0x37859 號。
下班真夠早的,我一溜小跑,來到 0x37859 號,在辦事窗口小姐姐的幫助下查到了 “xyz” 的進(jìn)程id:8681, 按照要求,我把它記錄在了變量 $process_id 中。
殺手組織
這個工作看起來很簡單嘛, 我馬上查看第二條指令,真是不看不知道,一看嚇一跳,這條指令是:
- kill $process_id
我揉揉眼睛再確認(rèn)一下,沒錯,就是 kill , 那個 $process_id 不就是我剛剛查出來的嗎?8681!沒想到查詢這個 pid 的值居然是為了干掉這個進(jìn)程, 也不知道他做錯了什么。
我還沒辦過這種差呢,kill,看這個名字這是個殺手組織吧,肯定都是殺進(jìn)程不眨眼的那種,太可怕了!
這個叫 kill 的店可真不好找,多虧 cp 旗艦店的小二給我指了一條路,我才來到這個店鋪門口, 我以為這里肯定是嚴(yán)密把守,門口會有彪形大漢站崗,沒想到只是一個平平常常的小店!門口掛著兩個隨風(fēng)飄揚的大燈籠,上面寫著:“送” “信”。
這就是 kill 門店?殺手組織的駐地就這樣?懷著忐忑的心情,我走進(jìn)店中。
出乎我的意料, 小二非常熱情,他馬上滿臉堆笑地迎上來:“客官您要辦點什么業(yè)務(wù)呢,咱們這兒的信件是最全的,應(yīng)有盡有,任君挑選”。
看到墻上還貼著 "微笑服務(wù)” 四個字,我差點懷疑走錯片場了,我把他拉到一邊,壓低聲音說:"我不是來送信的,我這次來是要殺一個進(jìn)程,你們能辦嗎?"
我一邊說,一邊做了一個殺頭的手勢。
小二看了看我的任務(wù)單,說道:“客官是第一次來吧,你要辦的這個是常規(guī)業(yè)務(wù),我們最拿手了。不過你說的這個殺進(jìn)程我們保證不了,小店只提供送信服務(wù), 這封信送出去,進(jìn)程能不能殺得掉就不歸我們管了。”
“你們不是負(fù)責(zé)殺人嗎?怎么和送信這種沒技術(shù)含量的業(yè)務(wù)扯到一起了?”
小二笑道:“這是外界對我們的誤解了,我們不是一個殺手組織, 我們的業(yè)務(wù)很單純,只負(fù)責(zé)送信給進(jìn)程。而且這封信還得通過內(nèi)核老大轉(zhuǎn)交呢!比如你這次要 kill 8681, 我們就會發(fā)送一封叫做 SIGTERM 的信,意思是終止進(jìn)程。”
小二邊給我解釋,邊掏出系統(tǒng)調(diào)用專用手機(jī)發(fā)送了一個 "15 8681",這下我知道了, SIGTERM 對應(yīng)的信號值就是 15,小二通過系統(tǒng)調(diào)用發(fā)給了內(nèi)核。
“殺人” 的活兒就這么辦完了,我付了 3 塊的 CPU 幣, 滿懷疑慮地離開了這個“送信”的店鋪。
死循環(huán)
下一個指令竟然是個 while 循環(huán),它讓我隔一會兒就去進(jìn)程管理局查詢一下,直到 $process_id (也就是 8681 )不存在了才能執(zhí)行后續(xù)的任務(wù)。 我心里很清楚,這是要保證那個8681的進(jìn)程被殺死。
我一趟趟地往進(jìn)程管理局跑,累死個人了,可是這個進(jìn)程管理局的小姐姐每次都告訴我,這個 8681 號進(jìn)程活得好好的,正在shell大街的某個角落呼呼大睡呢!
肯定是“送信”的那個店小二把我騙了 !趁著 while 循環(huán)的間隙,我怒氣沖沖地回到了“送信”店鋪,質(zhì)問小二為什么收了我的錢不干活!
店小二脾氣挺好:“我們送信,絕對不會出錯的,但是,我們不能保證進(jìn)程被殺死。”
我說到:“那你給我退錢,我去找別的殺手。”
小二哈哈笑道:“客官有所不知,你到哪里都是一樣,對于 SIGTERM 信號,一般內(nèi)核老大確實會干掉對應(yīng)進(jìn)程,但如果進(jìn)程提前打過招呼,留下了一個自己的 SIGTERM 處理函數(shù),那么按照約定老大就只會調(diào)用下這個函數(shù)。函數(shù)里面進(jìn)程也許會做一些掃尾工作再退出,也許壓根就不退出,繼續(xù)逍遙快活。甚至進(jìn)程還可以直接屏蔽掉這個信號呢。我猜 8681 號進(jìn)程就是如此,賴著不退出。”
我滿臉愁色:“那這樣不相當(dāng)于從生死簿上勾去姓名,長生不老了嗎?!不管怎么樣,你得把它給殺掉!"
小二聞言露出了老江湖的笑容:“客官聽說過江湖傳言嗎?kill 一笑,生死難料,杠九一(安)排 ,世間白來。”
我若有所悟,連忙問道: "杠九是什么意思,是 9 號信件嗎?"
小二聞言露出贊許的目光:“看來你還是挺機(jī)靈的,一點就通。9 號信件那就是大名鼎鼎的 SIGKILL 了。雖然大多數(shù)信件都允許進(jìn)程注冊自定義信件處理函數(shù),但有幾個特別的信件,例 SIGKILL 和 SIGSEGV 是不允許注冊處理函數(shù)的,一旦內(nèi)核老大收到 我們送的 SIGKILL 信號,那就相當(dāng)于殺無赦,斬立決,手起刀落毫不遲疑的。一般用 kill 殺不掉的進(jìn)程,用上 kill -9 就可以干掉了。”
原來如此 !可是雖然知道了 SIGKILL ,但悲慘的是我只能按照任務(wù)單來執(zhí)行任務(wù),不能擅自更改為 kill -9 $process_id
天哪!難道我真的就被困在這里了嗎?!
定身法
生活不易,進(jìn)程嘆氣,我無精打采地準(zhǔn)備出門,繼續(xù)去查詢進(jìn)程,估計進(jìn)程管理局的小姐姐都很煩我了,每次都問同一個問題。
就在我準(zhǔn)備邁出 kill 小店時,怪事發(fā)生了,我動不了了!就像是中了定身術(shù)一樣。
小二跑上前來看了看說 :“哈哈, 看來你被掛起了!”
我焦急地問:“說清楚點,什么是掛起呀?”
小二從柜臺拿出了一張信件清單給我看:“喏,看到這個 SIGTSTP 沒,它會讓進(jìn)程掛起,我們店也有這項業(yè)務(wù)的。估計是人類程序員發(fā)現(xiàn)你遲遲沒有執(zhí)行下一個任務(wù),開始調(diào)試了。只要他們按下 Ctrl+Z,就會發(fā)出 SIGTSTP ,內(nèi)核老大就把你掛起了。你小子還挺幸運的,只是被掛起,上次有個進(jìn)程辦事出了點小差錯,直接就被人類按下了 Ctrl+C,用 SIGINT 給干掉了。慢慢等著吧,人類慢得很吶!”
在 kill 小店真是學(xué)了不少東西,真希望人類程序員也能快點學(xué)會這些知識,解救我于水火之中。
不過我顯然高估了人類,足足過了十幾秒,我才看到另一個進(jìn)程來到了 kill 小店中,他手中的任務(wù)單赫然寫著 "kill -9 8681", 謝天謝地,人類找到解決方法了。
又過了漫長的好幾秒,我才感到身體一輕,又可以活動了。
舒展下筋骨,我連忙跑到進(jìn)程管理局去查詢,這次查詢結(jié)果是 "查無此pid",哈哈,我終于可以擺脫這個循環(huán),繼續(xù)我任務(wù)單的下一條了。
尾聲
離開之前,進(jìn)程管理局的小姐姐還告訴了我一個小道消息,原來這個害我不淺的 8681 進(jìn)程并不是故意忽略 SIGTERM 的,他注冊了一個信號處理函數(shù),打算打印一句 log 再退出,但在執(zhí)行的時候竟然死鎖了,據(jù)說原因是打印函數(shù)不屬于異步信號安全的函數(shù),不能在信號處理時調(diào)用。
我管不了那么多了,趕緊去執(zhí)行下一個任務(wù),要不然又要被掛起了......