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























