进程等待
進程等待于原因
一個進程雖然退出了,但是該進程還保留了很多對于程序員或者系統(tǒng)管理員來說有用 的信息。比如,該進程識如何退出的,是正常退出,還是出現了錯誤,還是被其他進程結束掉,總結來說這個進程的退出碼是什么;這個進程占用的CPU時間還有用戶時間是多少。
這個時候為了回收這些信息我們就需要父進程調用進程等待函數來進程 信息的一些回收工作,如果一個進程退出了但是一直沒有父進程回收它,這個進程就變成了僵尸進程,又名僵死進程。
父進程調用等待函數會發(fā)生的情況
- 如果其所有子進程都還在運行,則父進程阻塞;可以這樣理解,我們只有一個CUP,這個時候如果其他的子進程在運行的話,我們就沒有其他的時間和精力去處理這個已經死亡的進程,所以這個時候父進程會一直阻塞住
- 如果一個子進程已經死亡,正在等待父進程回收其終止狀態(tài),則這個時候父進程調用等待函數,并立即返回
- 如果沒有任何子進程終止,父進程依然調用了等待函數,則這個時候直接出錯返回
進程等待函數
包含頭文件
#include<sys/types.h>
#include<sys/wait.h>
- wait函數
?pid_t wait(int*status);
?返回值:成功則返回等待進程的PID,失敗則返回-1
?參數:這個status可以是我們之前已經定義的一個int status;我們通過下面即將介紹的一個宏函數,然后把status傳入進去可以獲取退出狀態(tài);如果我們不關心這個退出狀態(tài)的話,我們可以給這個參數填寫上NULL waitpid
?pid_t waitpid(pid_t pid, int *status, int options
?返回值:- 當正常返回的時候waitpid返回收集到的子進程的進程ID;
- 如果設置了選項WNOHANG,而調用中waitpid發(fā)現沒有已退出的子進程可收集,
則返回0; - 如果調用中出錯,則返回-1,這時errno會被設置成相應的值以指示錯誤所在;
- 當pid所指示的子進程不存在,或此進程存在,但不是調用進程的子進程,waitpid就
會出錯返回,這時errno被設置為ECHILD.
? 參數:
- pid:
pid=-1,等待任一個子進程。與wait等效。
Pid>0.等待其進程ID與pid相等的子進程。
Pid==0等待其組ID等于調用進程組ID的任一個子進程。
Pid<-1等待其組ID等于pid絕對值的任一子進程。
(這個時候我們可以在waitpid這個函數的第一個參數中填寫如相應的數字,比如-1,這個時候就可以等待任意的一個進程;如果我們填寫 的是一個大于0的一個數字,一般這個數字就是一個進程號,就是某一個特定的進程,我們就可以等待這個特定的進程;其他的一個參數設置類似) - status:
WIFEXITED(status) :
若為正常終止子進程返回的狀態(tài)(這里就是一個返回狀態(tài)),則為真。 (查看進程是
否是正常退出)
WEXITSTATUS(status) :
若WIFEXITED非零,提取子進程退出碼。(查看進程
的退出碼) - options:
WNOHANG :若pid指定的子進程沒有結束,則waitpid()函數返回0,不予以等待。
若正常結束,則返回該子進程的ID。
程序實例講解
進程的阻塞等待方式
#include<stdio.h>
#include<stdlib.h>
#include<sys/types.h>
#include<sys/wait.h>
#include<unistd.h>
int main()
{pid_t sunpid = fork();if(sunpid < 0){printf("fork error\n");}else if(sunpid == 0) //子進程{printf("i am sun\n");//sleep(10);printf("i will exit. my pid is %d\n",getpid());sleep(10);exit(9); //我剛剛測試這個代碼的時候,一直是等待失敗,可能 和我這個exit有關,我不用這個了,直接什么都不用,看看是什么效果}else //父進程{int status;pid_t sun;//這里調用的是阻塞式等待,所以預期的結果是子進程打印出了i am sun之后五秒中之后,子進程打印i will exit ...然后父進程打印子進程的id,等待成功while(1){sleep(10);sun = wait(&status); //如果等待成功了返回等待進程的pid,如果失敗則返回-1if(sun == -1){printf("等待失敗\n");sleep(1);}else{printf("等待成功,子進程id是%d\n",sun);printf("返回碼為%d\n",WEXITSTATUS(status));printf("返回狀態(tài)為%d\n",WIFEXITED(status));break;}}}return 0;
}
總結
- 上一篇: Linux的僵尸进程
- 下一篇: 进程程序替换