Linux下進程的各種狀態
我的問題來了,假如是一個進程使用了udp的阻塞recvfrom()方法,在網絡連接沒有數據到達時,進程會在這個方法上面阻塞?這個阻塞的意思是進程會進入等待隊列,此時的進程處于下列的什么狀態??然后cpu進而調度其他進程。。。還是cpu仍然給此進程分配時間片在它自己的時間片上讓其阻塞在此方法上,這不是浪費cpu時間??
我是真的得好好看看操作系統的書了
D Uninterruptible sleep (usually IO)
不可中斷的深度睡眠,一般由IO引起,同步IO在做讀或寫操作時,此進程不能做其它事情,只能等待,這時進程處于這種狀態,如果程序采用異步IO,這種狀態應該就很少見到了
R Running or runnable (on run queue)
進程處于運行或就緒狀態
S Interruptible sleep (waiting for an event to complete)
可接收信號的睡眠狀態,sleep函數可演示這種狀態
T Stopped, either by a job control signal or because it is being traced.
被ctrl+z中斷或被trace
W paging (not valid since the 2.6.xx kernel)
X dead (should never be seen)
進程已經完全死掉,不可能看見這種狀態的
Z Defunct ("zombie") process, terminated but not reaped by its parent.
進程已經終止,但是其父進程沒有來及處理它,多進程寫不好的話,這種狀態是常見的
For BSD formats and when the stat keyword is used, additional characters may
be displayed:
< high-priority (not nice to other users)
N low-priority (nice to other users)
L has pages locked into memory (for real-time and custom IO)
s is a session leader
l is multi-threaded (using CLONE_THREAD, like NPTL pthreads do)
+ is in the foreground process group
關于D和Z一段有趣的解釋:
有一類垃圾卻并非這么容易打掃,那就是我們常見的狀態為 D (Uninterruptible sleep) ,以及狀態為 Z (Zombie) 的垃圾進程。這些垃圾進程要么是求而不得,像怨婦一般等待資源(D),要么是僵而不死,像冤魂一樣等待超度(Z),它們在 CPU run_queue 里滯留不去,把 Load Average 弄的老高老高,沒看過我前一篇blog的國際友人還以為這兒民怨沸騰又出了什么大事呢。怎么辦?開槍!kill -9!看你們走是不走。但這兩種垃圾進程偏偏是刀槍不入的,不管換哪種槍法都殺不掉它們。無奈,只好reboot,像剿滅禽流感那樣不分青紅皂白地一律撲殺!
怨婦 D,往往是由于 I/O 資源得不到滿足,而引發等待,在內核源碼 fs/proc/array.c 里,其文字定義為“ "D (disk sleep)", /* 2 */ ”(由此可知 D 原是Disk的打頭字母),對應著 include/linux/sched.h 里的“ #define TASK_UNINTERRUPTIBLE 2 ”。舉個例子,當 NFS 服務端關閉之時,若未事先 umount 相關目錄,在 NFS 客戶端執行 df 就會掛住整個登錄會話,按 Ctrl+C 、Ctrl+Z 都無濟于事。斷開連接再登錄,執行 ps axf 則看到剛才的 df 進程狀態位已變成了 D ,kill -9 無法殺滅。正確的處理方式,是馬上恢復 NFS 服務端,再度提供服務,剛才掛起的 df 進程發現了其苦苦等待的資源,便完成任務,自動消亡。若 NFS 服務端無法恢復服務,在 reboot 之前也應將 /etc/mtab 里的相關 NFS mount 項刪除,以免 reboot 過程例行調用 netfs stop 時再次發生等待資源,導致系統重啟過程掛起。
冤魂 Z 之所以殺不死,是因為它已經死了,否則怎么叫 Zombie(僵尸)呢?冤魂不散,自然是生前有結未解之故。在UNIX/Linux中,每個進程都有一個父進程,進程號叫PID(Process ID),相應地,父進程號就叫PPID(Parent PID)。當進程死亡時,它會自動關閉已打開的文件,舍棄已占用的內存、交換空間等等系統資源,然后向其父進程返回一個退出狀態值,報告死訊。如果程序有 bug,就會在這最后一步出問題。兒子說我死了,老子卻沒聽見,沒有及時收棺入殮,兒子便成了僵尸。在UNIX/Linux中消滅僵尸的手段比較殘忍,執行 ps axjf 找出僵尸進程的父進程號(PPID,第一列),先殺其父,然后再由進程天子 init(其PID為1,PPID為0)來一起收拾父子僵尸,超度亡魂,往生極樂。注意,子進程變成僵尸只是礙眼而已,并不礙事,如果僵尸的父進程當前有要務在身,則千萬不可貿然殺之。