當前位置:首頁 » 操作系統 » linuxwaitpid

linuxwaitpid

發布時間: 2023-08-03 11:58:45

A. linux中的defunct進程(僵屍進程)

一、什麼是defunct進程(僵屍進程)?
在 Linux 系統中,一個進程結束了,但是他的父進程沒有等待(調用wait / waitpid)他,那麼他將變成一個僵屍進程。當用ps命令觀察進程的執行狀態時,看到這些進程的狀態欄為defunct。僵屍進程是一個早已死亡的進程,但在進程表(processs table)中仍佔了一個位置(slot)。
但是如果該進程的父進程已經先結束了,那麼該進程就不會變成僵屍進程。因為每個進程結束的時候,系統都會掃描當前系統中所運行的所有進程,看看有沒有哪個進程是剛剛結束的這個進程的子進程,如果是的話,就由Init進程來接管他,成為他的父進程,從而保證每個進程都會有一個父進程。而Init進程會自動wait其子進程,因此被Init接管的所有進程都不會變成僵屍進程。
二、 Linux下進程的運作方式
如果子進程先於父進程退出, 同時父進程又沒有調用wait/waitpid,則該子進程將成為僵屍進程。如果該進程的父進程已經先結束了,那麼該進程就不會變成僵屍進程。因為每個進程結束的時候,系統都會掃描當前系統中所運行的所有進程,看看有沒有哪個 進程是剛剛結束的這個進程的子進程,如果是的話,就由Init進程來接管他,成為他的父進程,從而保證每個進程都會有一個父進程。而Init進程會自動 wait其子進程,因此被Init接管的所有進程都不會變成僵屍進程。
每個 Linux進程在進程表裡都有一個進入點(entry),核心進程執行該進程時使用到的一切信息都存儲在進入點。當用 ps 命令察看系統中的進程信息時,看到的就是進程表中的相關數據。當以fork()系統調用建立一個新的進程後,核心進程就會在進程表中給這個新進程分配一個進入點,然後將相關信息存儲在該進入點所對應的進程表內。這些信息中有一項是其父進程的識別碼。
子進程的結束和父進程的運行是一個非同步過程,即父進程永遠無法預測子進程到底什麼時候結束。那麼會不會因為父進程太忙來不及 wait 子進程,或者說不知道子進程什麼時候結束,而丟失子進程結束時的狀態信息呢?
不會。因為 Linux提供了一種機制可以保證,只要父進程想知道子進程結束時的狀態信息,就可以得到。這種機制就是:當子進程走完了自己的生命周期後,它會執行exit()系統調用,內核釋放該進程所有的資源,包括打開的文件,佔用的內存等。但是仍然為其保留一定的信息(包括進程號the process ID,退出碼exit code,退出狀態the terminationstatus of the process,運行時間the amount of CPU time taken by the process等),這些數據會一直保留到系統將它傳遞給它的父進程為止,直到父進程通過wait / waitpid來取時才釋放。
也就是說,當一個進程死亡時,它並不是完全的消失了。進程終止,它不再運行,但是還有一些殘留的數據等待父進程收回。當父進程 fork() 一個子進程後,它必須用 wait() (或者 waitpid())等待子進程退出。正是這個 wait() 動作來讓子進程的殘留數據消失。
三、僵屍進程的危害
如果父進程不調用wait / waitpid的話,那麼保留的那段信息就不會釋放,其進程號就會一直被佔用,但是系統的進程表容量是有限的,所能使用的進程號也是有限的,如果大量的產生僵屍進程,將因為沒有可用的進程號而導致系統不能產生新的進程。
所以,defunct進程不僅佔用系統的內存資源,影響系統的性能,而且如果其數目太多,還會導致系統癱瘓。而且,由於調度程序無法選中Defunct 進程,所以不能用kill命令刪除Defunct 進程,惟一的方法只有重啟系統。
四、如何殺死defunct進程
defunct進程是指出錯損壞的進程,父子進程之間不會再通信。有時,它們會演變成「僵屍進程」,存留在你的系統中,直到系統重啟。可以嘗試 「kill -9」 命令來清除,但多數時候不管用。
為了殺死這些defunct進程,你有兩個選擇:
1.重啟你的計算機
2.繼續往下讀…
我們先看看系統中是否存在defunct進程:
$ ps -A|grep defunct
1
輸出
5259 ? 00:00:00 sd_cicero <defunct>
12214 pts/18 00:01:14 python <defunct>
16989 pts/18 00:04:43 python <defunct>
20610 pts/18 00:23:12 python <defunct>

看看這些進程的ID及其父進程ID:
$ ps -ef | grep defunct | more
UID PID PPID ...
==========================================================================
yourname 4653 6128 0 17:07 pts/18 00:00:00 grep --color=auto defunct
yourname 5259 5258 0 15:58 ? 00:00:00 [sd_cicero] <defunct>
yourname 12214 12211 4 16:41 pts/18 00:01:14 [python] <defunct>
yourname 16989 16986 20 16:45 pts/18 00:04:43 [python] <defunct>
yourname 20610 18940 99 16:48 pts/18 00:23:12 [python] <defunct>

UID:用戶ID
PID:進程ID
PPID:父進程ID
如果你使用命令 「kill -9 12214」 嘗試殺死ID為12214的進程,可能會沒效果。
我們來試一下
ps -A|grep defunct

輸出
5259 ? 00:00:00 sd_cicero <defunct>
12214 pts/18 00:01:14 python <defunct>
16989 pts/18 00:04:43 python <defunct>
20610 pts/18 00:23:12 python <defunct>

進程12214 仍然存才,說明用kill殺不掉它。
要想成功殺死該進程,需要對其父進程(ID為12211)執行kill命令( ps -A | grep defunct)。
我們來試一下
ps -A|grep defunct

輸出
5259 ? 00:00:00 sd_cicero <defunct>
16989 pts/18 00:04:43 python <defunct>
20610 pts/18 00:23:12 python <defunct>
[1] Killed bash main.sh

進程12214消失,說明可以通過kill僵屍進程的父進程來殺死僵屍進程。
如果前一個命令顯示無結果,那麼搞定!否則,可能你需要重啟一下系統。

參考鏈接: https://www.cnblogs.com/lfxiao/p/10837115.html

B. LINUX里,父進程退出了,子進程一定會退出嗎

不會,父進程退出後,子進程成為孤兒進程被init進程收養。如果需要用父進程回收子進程,就要在父進程里使用waitpid,這個函數會讓父進程阻塞,直到子進程執行完成。

C. Linux 如何使用`wait`等待所有子進程退出,而不是等待第一個子進程退出.希望能給出代碼片段

linux中的wait函數等到一個子進程退出就會返回,恢復到執行狀態。要想等所有子進程退出可以用waitpid函數
pid_t wait(pid_t pid,int * status,int options);
pid>0時,只等待pid與該參數相同的子進程,如果該子進程一直沒有退出,那麼父進程會一直阻塞;
pid=0時,會等待同一個進程組的子進程,若子進程加入了其他進程組,waitpid()不再關心它的狀態;
pid=-1時,waitpid()與wait()函數相同,將阻塞等待並回收一個子進程;
pid<-1時,會等待指定進程組的任何子進程,進程組的id等於pid的絕對值;

D. 自己編寫的Linux Web Server調用CGI程序時出現問題

如果你的程序中的 CGI 程物敬好檔序只能啟動罩襪慎一次,可能是因為你的程序沒有正確處理子進程退出的情況。
在調用 execvp 函數啟動子進程執行 CGI 程序時,子進程會替換掉父進程的代碼和數據空間,執行 CGI 程序。如果 CGI 程序執行完畢後正常退出,子進程會自動結束,父進程會收到子進程退出的信號。
在收到子進程退出的信號後,父進程應該調用 wait 或者 waitpid 函數等待子進程退出,並獲取子進程的退出狀態。如果父進程沒有調用 wait 或者 waitpid 等待子進程退出,子進程可能會變成僵屍進程,導致後續的 CGI 程序無法正常啟動。
因此,建議在父進程中調用 wait 或者 waitpid 等函數等待子進程退出,以避免出現僵屍進程的情況。
回答不易,請點個贊。

E. Linux下的c編程:系統調用

標準的c函數庫是所有的編譯都要具有的函數庫,(實際上還是略有不同),但是這些基本上實現方法略有不同,但是結果和標準是一樣的。但是linux的系統調用,調用是linux的系統庫,比如說unistd.h下的fork這個是Linux下特有,你在vs上,就沒有這個庫,也沒有這個函數。同樣在vs上寫c,你可以引入頭文件比如windows.h,顯然這個庫是Linux不具有的。簡單說系統調用庫根據具體的操作系統環境不同而不同,而c標准庫,是所有支持c語言編譯器都有的。

F. 在linux系統下實現對system() 函數對fork() ,exec(),waitpid()函數的調用。求大神解答

不知道你這實現這些函數的調用是什麼意思,是要重寫這些介面嗎?還是舉個例子說明?
我解釋一下吧:
(1)system()其實就是對fork()和exec()函數族等的封裝。
(2)fork()是用來產生子進程的,是現在我知道的唯一一個返回兩個值的函數(有過有另外的,麻煩網友指出),返回-1表示執行失敗;否則返回大於0的值時,表示是子進程的進程號,返回0時,表示父進程創建子進程成功。
(3)exec()不是一個函數,是函數族,有execl(),execv(),execle(),execve(),execlp(),execvp(),它們常用於子進程中「脫胎換骨」,就是父進程創建子進程後,子進程幾乎是父進程的拷貝(只有很少的東西不一樣,如進程號(PID)等),然後子進程調用exec()函數族執行其他的程序,即將原來進程的東西全部清除掉,稱為一個嶄新的進程,所以叫「脫胎換骨」。
(4)waitpid()是用在父進程中等待進程退出的,如果父進程不調用這個介面,那麼它有可能先於子進程退出,那麼子進程就會稱為孤兒進程,繼而被init進程(PID為1的進程,Linux啟動後第一個啟動的進程)收養。或者父進程並未退出,也未調用這個介面,但是子進程已經執行完成,那麼子進程就會成為一個僵屍進程。
具體例子在網上找找吧,都不是很難。

G. LINUX里,父進程退出了,子進程一定會退出嗎

不。
若父進程退出,子進程尚未結束,則子進程會被init進程領養,也就是說init進程將成為該子進程的父進程。
若希望父進程退出,子進程也退出的話,可以使用線程,因為若進程結束,則還沒結束的線程一定會立刻結束。或者如樓上所說,用信號,用atexit注冊一個退出時執行的函數,這個函數中發送信號給子進程即可。

熱點內容
tcl編譯器 發布:2025-03-13 23:52:59 瀏覽:321
linuxnamed 發布:2025-03-13 23:45:29 瀏覽:361
阿里雲30元伺服器 發布:2025-03-13 23:21:25 瀏覽:350
pythonstatvfs 發布:2025-03-13 23:14:55 瀏覽:953
火車上有密碼多少 發布:2025-03-13 23:14:10 瀏覽:865
解壓火柴 發布:2025-03-13 22:46:39 瀏覽:336
開機密碼在哪裡存著 發布:2025-03-13 22:27:22 瀏覽:952
光流場演算法 發布:2025-03-13 21:35:51 瀏覽:895
免編程軸控 發布:2025-03-13 21:19:24 瀏覽:780
新買的車都要配置哪些 發布:2025-03-13 20:42:50 瀏覽:901