日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 运维知识 > linux >内容正文

linux

linux结束进程_生人勿近之Linux里养僵尸

發布時間:2024/1/23 linux 38 豆豆
生活随笔 收集整理的這篇文章主要介紹了 linux结束进程_生人勿近之Linux里养僵尸 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

Linux里養僵尸是怎么回事呢?Linux相信大家都很熟悉,但是Linux里養僵尸是怎么回事呢,下面就讓小編帶大家一起了解吧。

- 1?-

上一篇挖了個 SIGHUP 的坑,這篇試著填一下。

之前在《程序員面試指北:面試官視角》里面說過,在結構化面試中,我們會從各個方向去考查候選人,其中之一是操作系統。

上篇介紹了一套題,我還有另一套,一般這么開場:

在終端下啟動一個命令,如果在命令結束前關掉終端,它還能正常運行嗎?


- 2?-

這其實是一個很常見的case,但凡 Linux 或者 Mac 用得多一點,都會遇到。

在我還是一個窮酸學生的2009年,每個月都需要支付 20 元巨款(當時能買3根鴨脖),通過一個禁止分享網絡的認證客戶端接入校園網。

為了共建和諧宿舍?節省網費,我歷經千辛萬苦,交叉編譯開源的Linux認證客戶端,集成到固件里,并刷到了我的 NETGEAR 路由器上。

然后山水 BBS 的 Linux 版主把我的帖子置頂了 11 年。可見他有多痛恨禁止共享網絡。

這么一回憶,感覺自己的共享經濟思維真是前衛,當時怎么就沒想到去搞共享單車呢?

扯遠了,在搗騰的過程中,我就踩了這么個坑:當我ssh到路由器上、剛啟動認證時,能夠正常聯網;但是退出ssh后一會,網就斷了。

經過一番搗騰后發現,只要一退出ssh,認證程序就涼了,而不是繼續在后臺保持和認證服務器的通信。


- 3 -

所以前面那個問題,我以為大部分候選人應該會回答“否”,但沒想到竟然還有不少人回答“是”。

其實回答“是”也沒什么錯,因為確實也有些命令不會隨著終端關閉而結束。

問題是當我追問當時執行的是什么命令時,候選人往往又說不出個所以然來。

(借學長的表情一用)

然后我就感到很強的挫敗感:這不按劇本來,沒法問了啊……只好換題。

當然大部分候選人確實被坑過,于是我可以接著問:

如果確實需要在后臺繼續執行命令怎么辦呢?

有些人只記得要在后面加個 & ;但也有不少人知道前面還得加個 nohup,就像這樣:

$ nohup python process.py &[1]?1806824nohup:?ignoring?input?and?appending?output?to?'nohup.out'

注:其實我更喜歡 screen(或 tmux),偶爾也用 setsid。

然后就可以放心地關閉終端?開始放羊?了。

但我的套題還沒結束:為什么加上 nohup 就可以讓進程在后臺繼續運行呢?

(這表情熟悉嗎)


- 4 -

鋪墊了這么多,總算是可以開始填坑了。

答案其實很好找,man nohup 就能看到:

The?nohup?utility?invokes?utility?with?its?arguments?and?at?this?time?sets?the?signal?SIGHUP?to?be?ignored

nohup工具在啟動命令的同時會將 SIGHUP 信號設置為忽略。

而關于 SIGHUP,Wikipedia原文是這樣介紹的:

On POSIX-compliant platforms, SIGHUP ("signal hang up") is a signal sent to a process when its controlling terminal is closed.

wikipedia.org/wiki/SIGHUP

對于 POSIX 兼容的平臺(如Unix、Linux、BSD、Mac),當進程所在的控制終端關閉時,系統會給進程發送 SIGHUP 信號(Signal Hang Up,掛斷信號)。

為什么叫 SIGHUP 呢?(嚴正申明:這一問不在套題里)

我們知道,在上古時代,捉 bug 就已經是碼農的必備技能(更準確地說是 moth)。

(我總覺得這個圖是假的)

到了遠古時代,他們不再需要去機房,通過基于 RS-232 協議的串行線路連接到大型機的終端上,就可以開始收福報。

收完福報,程序員通知自己的貓(modem)掛斷(Hang Up)連接;大型機的 OS 檢測到連接斷開,就會給進程發送信號 —— 所以這信號被稱為 SIGHUP 。

這果然是毫無卵用的知識啊。


- 5 -

很多同學在操作系統的課程上學習了“進程間的通信方式有信號、管道、消息隊列、共享內存……”,但是對信號到底是個什么東西,并沒有現實的概念。

課堂教學的理論和實踐往往是割裂的,在此特別推薦《Unix環境高級編程》(簡稱APUE)。

APUE在 1.9 - 信號 中寫到:信號是通知進程已發生某種條件的一種技術。

而在 Linux/Unix 下,進程對信號的處理有三種選擇:

  • 按系統默認方式處理

  • 提供一個回調函數

  • 或忽略該信號(有些信號例外,不允許被忽略)

以 SIGHUP 信號為例,系統默認處理方式就是結束進程

當然終端下打開的第一個進程通常都是shell(例如bash)。shell會給 SIGHUP 信號注冊一個回調函數,用于給該 shell 下所有的子進程發送 SIGHUP 信號,然后再主動退出。

對于求生欲很強的程序(例如nohup),可以主動選擇忽略該信號

有一些進程本來就被設計成在后臺運行,不需要控制終端,因此它們將?SIGHUP 挪作它用,一個常見的用法就是重新讀取配置文件(例如Apache、Nginx),上篇提到的 logrotate 正是利用了這一點。

終于填完了坑。


- 6 -

說了這么多都還是紙上談兵,實操中如何主動忽略 SIGHUP 呢?

實際上也很簡單,使用 Linux 的 signal 系統調用即可:

#include #include int main() { signal(SIGHUP, SIG_IGN); sleep(1000); return 0;}

不妨試試看,編譯運行起來,即使關閉終端,它也會在后臺繼續運行。

signal 也可以用于指定回調函數(或重置為系統默認處理方式),這里就不展開了,感興趣的同學可以參考 APUE 里的代碼,以及閱讀 signal 的manual。

使用回調函數還需要注意一個坑:

由于回調函數可能在任意時刻被觸發,因此要避免調用不可重入的函數(典型如printf)。常見的做法是 set 一個 flag,然后在程序的主循環中檢測該 flag,再按需執行相應任務。


- 7 -

SIGHUP 只是常見的一個信號,在 Linux 下,信號還有大量其他的場景和應用。

當你按下 Ctrl + C ,就是給進程發送了一個 SIGINT 信號。

當你執行 kill -9 $PID,就是給進程發送了一個 SIGKILL 信號。可能和你期望有出入的是,SIGKILL 是可以被進程忽略的。所以有時候你得用 SIGTERM。

你還可以使用可自定義的 SIGUSR1、SIGUSR2、SIGURG 來實現一些功能,比如《踩坑記#2:Go服務鎖死》中提到 Golang 在其 goroutine 調度中使用了 SIGURG 。


- 8 -

這次就不總結了,最后再用一個和信號有關的 case 收尾。

Linux 內核會為每一個進程分配一個 task_struct 結構體,用于保存進程的相關信息。

在進程死亡后,系統會發送一個 SIGCHLD 信號給它的父進程。

正確的父進程實現,通常應當使用 wait 系統調用來給子進程收尸 —— 父進程往往需要知道子進程結束這個事件,而且可能還需要得知其退出原因(exit code)。

然后內核才會將對應的 task_struct 釋放。

如果父進程沒有收尸,task_struct 里的 state 會一直保持為 EXIT_ZOMBIE,這時在 ps 或 top 等命令里,就可以看到該進程的狀態為 Z ,而且無法被 kill 。

這就是所謂的僵尸進程,這時候你找九叔都沒用。

(大半夜找這圖還挺滲人的)

所以Linux里養僵尸,其實就是子進程死了父進程不收尸,大家可能會很驚訝Linux里怎么會養僵尸呢?但事實就是這樣,小編也感到非常驚訝。

這就是關于Linux里養僵尸的事情了,大家有什么想法呢,歡迎在評論區告訴小編一起討論哦!


推薦閱讀

  • 程序員面試指北:面試官視角

  • 踩坑記:go服務內存暴漲

  • TCP:學得越多越不懂

  • UTF-8:一些好像沒什么用的冷知識

  • [譯] C程序員該知道的內存知識 (1)


總結

以上是生活随笔為你收集整理的linux结束进程_生人勿近之Linux里养僵尸的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。