根據任務,程式必須使用fork()創建自己的副本來處理任務。子行程運行時不能阻塞父行程。
但是,我遇到了測驗程式的奇怪行為。根據 pgrep 的結果,子行程在父程式完成執行之前不會終止。每次呼叫 fork() 時,pgrep 都會顯示行程的數量在增加,但它們并沒有終止。
我撰寫了一個簡單的程式,它運行了將近 35 秒并產生了 3 次子行程,它應該在 5 秒后退出:
#include <stdio.h>
#include <unistd.h>
int main(int argc, char* argv[])
{
for (int i = 1; i < 36; i ) {
if (i % 10 == 0) {
pid_t forkrank = fork();
if (forkrank == 0) {
printf("forked process starts\n");
sleep(5);
return 1;
}
}
sleep(1);
}
return 0;
}
但是在執行程序中,pgrep 顯示正在運行的行程在父行程結束之前不會終止:

但是如果我添加一個阻塞代碼來等待子行程執行的結果,那么其他行程就會正確終止:
#include <stdio.h>
#include <unistd.h>
#include <sys/wait.h>
int main(int argc, char* argv[])
{
for (int i = 1; i < 36; i ) {
if (i % 10 == 0) {
pid_t forkrank = fork();
if (forkrank == 0) {
printf("forked process starts\n");
sleep(5);
return 1;
}
int wstatus;
waitpid(forkrank, &wstatus, 0);
int retValue = WEXITSTATUS(wstatus);
}
sleep(1);
}
return 0;
}
pgrep:

為什么會這樣?如何在不阻塞主行程的情況下終止子行程?
uj5u.com熱心網友回復:
你可以做一個非阻塞等待。這是通過將WNOHANG標志作為第三個引數傳遞給waitpid. 您還可以為第一個引數傳遞 -1 以允許父級等待任何 pid。然后,您可以在主回圈中呼叫 towaitpid之后呼叫 to 。sleep
#include <stdio.h>
#include <unistd.h>
int main(int argc, char* argv[])
{
for (int i = 1; i < 36; i ) {
if (i % 10 == 0) {
pid_t forkrank = fork();
if (forkrank == 0) {
printf("forked process starts\n");
sleep(5);
return 1;
}
}
sleep(1);
waitpid(-1, NULL, WNOHANG);
}
return 0;
}
uj5u.com熱心網友回復:
恰當的說法是收割孩子。
這是使用wait/完成的waitpid。較早的答案顯示了如何使用輪詢來執行此操作,這需要更改您的程式以定期呼叫waitpid. 但也可以不進行此類更改。
要在孩子退出時自動收割,請使用sigaction安裝一個 SIGCHLD 處理程式,該處理程式呼叫waitpid(-1, NULL, WNOHANG)直到它回傳一個0or -1。
這有一個副作用。阻止系統呼叫現在可能會失敗并出現錯誤EINTR,除非您自動重新啟動它們。
您還可以守護子行程,使其完全獨立于父行程。該程序使它們成為init(pid 1)的孩子,并自動獲得終止的孩子。
uj5u.com熱心網友回復:
您可以通過將標志 WNOHANG 作為選項傳遞給 wpaitpid 來做到這一點 請參閱 (2):如果沒有子行程退出,則 waitpid WNOHANG 立即回傳。
waitpid(-1, NULL, WNOHANG);
轉載請註明出處,本文鏈接:https://www.uj5u.com/caozuo/487150.html
