本章包含內(nèi)容有:
?
1 進(jìn)程標(biāo)識(shí)符(Process Identifiers)每個(gè)進(jìn)程都有一個(gè)唯一的標(biāo)識(shí)符,進(jìn)程ID(process ID)。
進(jìn)程的ID是可重用的,如果一個(gè)進(jìn)程被終止,那么它的進(jìn)程ID會(huì)被系統(tǒng)回收,但是會(huì)延遲使用,防止該進(jìn)程ID標(biāo)識(shí)的新進(jìn)程被誤認(rèn)為是以前的進(jìn)程。
三個(gè)特殊ID的進(jìn)程:
獲取進(jìn)程各種ID的相關(guān)函數(shù):
函數(shù)聲明:
#include <unistd.h>
pid_t getpid(void); ? ? // Returns: process ID of calling process
pid_t getppid(void); ? ? ? ?// Returns: parent process ID of calling process
uid_t getuid(void); ? ? ? ?// Returns: real user ID of calling process
uid_t geteuid(void); ? ? ? // Returns: effective user ID of calling process
gid_t getgid(void); ? ? ? ?// Returns: real group ID of calling process
gid_t getegid(void); ? ? ? ?// Returns: effective group ID of calling process
這里的各種ID在前面第三篇中有說明,http://www.CUOXin.com/suzhou/p/4295535.html
?
2 fork函數(shù)fork函數(shù)用于一個(gè)已存在的進(jìn)程創(chuàng)建一個(gè)新的進(jìn)程。
函數(shù)聲明:
#include <unistd.h>
pid_t fork(void);
函數(shù)細(xì)節(jié):
Example:
#include "apue.h"
?
int ? ? globvar = 6;? ? ? ? /* external variable in initialized data */
char? ? buf[] = "a write to stdout/n";
?
int
main(void)
{
? ? int ? ? var;? ? ? ? /* automatic variable on the stack */
? ? pid_t ? pid;
?
? ? var = 88;
? ? if (write(STDOUT_FILENO, buf, sizeof(buf)-1) != sizeof(buf)-1)
? ? ? ? err_sys("write error");
? ? printf("before fork/n");? ? /* we don't flush stdout */
?
? ? if ((pid = fork()) < 0) {
? ? ? ? err_sys("fork error");
? ? } else if (pid == 0) {? ? ? /* child */
? ? ? ? globvar++;? ? ? ? ? ? ? /* modify variables */
? ? ? ? var++;
? ? } else {
? ? ? ? sleep(2); ? ? ? ? ? ? ? /* parent */
? ? }
?
? ? printf("pid = %ld, glob = %d, var = %d/n", (long)getpid(), globvar,
? ? ? var);
? ? exit(0);
}
執(zhí)行結(jié)果:
pid為12291的進(jìn)程為子進(jìn)程,對(duì)變量glob和var進(jìn)行了加1。
當(dāng)把輸出重定向到一個(gè)文件時(shí),我們發(fā)現(xiàn)結(jié)果和直接輸出到終端中不太一樣:
原因:?
?
文件共享(File Sharing)當(dāng)調(diào)用fork函數(shù)時(shí),父進(jìn)程的所有打開的文件描述符都會(huì)復(fù)制一份到子進(jìn)程中,包括文件偏移量(file offset)。
所以當(dāng)父子進(jìn)程同時(shí)寫文件時(shí),他們的操作都會(huì)更新同一個(gè)文件偏移量(file offset),加入子進(jìn)程向文件中寫入了一部分?jǐn)?shù)據(jù),同時(shí)更新了file offset,那么父進(jìn)程進(jìn)行寫入操作時(shí),會(huì)使用跟新以后的offset,從而避免了覆蓋了子進(jìn)程寫入的數(shù)據(jù)。
父子進(jìn)程共享文件如下圖所示:
我們可以發(fā)現(xiàn),父子進(jìn)程擁有相同的文件描述符,又沒有其他的同步方式,所以他們的輸出可能會(huì)混起來(intermixed)。
fork之后,常見的處理父子進(jìn)程擁有的文件描述符有兩種方式:
除了打開的文件描述,其他的子進(jìn)程會(huì)繼承自父進(jìn)程的內(nèi)容包括:
父子進(jìn)程不同的地方包括:
?
3 vforkvfork和fork有相同的返回值。
vfork和fork的不同點(diǎn):
?Example:
#include "apue.h"
?
int ? ? globvar = 6;? ? ? ? /* external variable in initialized data */
?
int
main(void)
{
? ? int ? ? var;? ? ? ? /* automatic variable on the stack */
? ? pid_t ? pid;
?
? ? var = 88;
? ? printf("before vfork/n"); ? /* we don't flush stdio */
? ? if ((pid = vfork()) < 0) {
? ? ? ? err_sys("vfork error");
? ? } else if (pid == 0) {? ? ? /* child */
? ? ? ? globvar++;? ? ? ? ? ? ? /* modify parent's variables */
? ? ? ? var++;
? ? ? ? _exit(0); ? ? ? ? ? ? ? /* child terminates */
? ? }
?
? ? /* parent continues here */
? ? printf("pid = %ld, glob = %d, var = %d/n", (long)getpid(), globvar,
? ? ? var);
?
? ? exit(0);
}
運(yùn)行結(jié)果:
?
4 進(jìn)程退出和僵尸進(jìn)程正常退出:三個(gè)函數(shù)exit,?
如果子進(jìn)程不正常退出,則內(nèi)核保證記錄該進(jìn)程的異常退出狀態(tài),該進(jìn)程的父進(jìn)程可以通過調(diào)用wait或者waitpid函數(shù)獲取該子進(jìn)程的異常退出狀態(tài)。
如果父進(jìn)程在子進(jìn)程之前終止,則init進(jìn)程成為該子進(jìn)程的父進(jìn)程。從而保證每個(gè)進(jìn)程都有父進(jìn)程。
如果子進(jìn)程先終止(異常終止或者正常退出),內(nèi)核會(huì)保存該子進(jìn)程的部分信息,包括進(jìn)程pid,進(jìn)程終止時(shí)的狀態(tài)和該進(jìn)程占用的CPU時(shí)間,同時(shí)內(nèi)核會(huì)清除該進(jìn)程占用的內(nèi)存,關(guān)閉所有已經(jīng)打開的文件描述符。父進(jìn)程可以通過檢查該信息獲取子進(jìn)程的終止情況。
如果子進(jìn)程先終止,而沒有父進(jìn)程調(diào)用waitpid獲取該子進(jìn)程的信息,那么這種進(jìn)程被成為僵尸進(jìn)程。使用ps命令可以看到僵尸進(jìn)程的相關(guān)信息。
如果父進(jìn)程為init進(jìn)程,那么子進(jìn)程異常終止并不會(huì)成為僵尸進(jìn)程,因?yàn)閕nit進(jìn)程會(huì)對(duì)它的所有子進(jìn)程調(diào)用wait函數(shù)獲取子進(jìn)程的終止?fàn)顟B(tài)。
?
5 wait和waitpid函數(shù)子進(jìn)程終止,內(nèi)核會(huì)向父進(jìn)程發(fā)送SIGCHLD信號(hào)。父進(jìn)程默認(rèn)的行為是忽略該信號(hào),父進(jìn)程也可以設(shè)置一個(gè)信號(hào)處理函數(shù),當(dāng)捕捉到該信號(hào)時(shí),調(diào)用該處理函數(shù),在后面的相關(guān)章節(jié)會(huì)介紹信號(hào)相關(guān)的概念。
本節(jié)介紹的wait和waitpid函數(shù)的作用是:
需要注意的一點(diǎn)是,如果我們?cè)诮邮盏絊IGCHLD信號(hào)后,調(diào)用wait函數(shù),則該函數(shù)會(huì)立刻返回。在其他情況下調(diào)用wait函數(shù),則會(huì)阻塞。
函數(shù)聲明:
#include <sys/wait.h>
pid_t wait(int *statloc);
pid_t waitpid(pid_t pid, int *statloc, int options);?
// Both return: process ID if OK, 0,or -1 on error
兩個(gè)函數(shù)之間的區(qū)別:
函數(shù)細(xì)節(jié):
返回值檢查:
使用四個(gè)宏來檢查wait和waitpid函數(shù)來獲取子進(jìn)程的終止?fàn)顟B(tài)(terminated status),如退出狀態(tài),信號(hào)值等信息。
四個(gè)宏的具體說明見下表所示:
pid的取值對(duì)waitpid函數(shù)行為的影響:
參數(shù)option的取值:
waitpid函數(shù)提供了三個(gè)wait沒有的特性:
?
Example:#include "apue.h"
#include <sys/wait.h>
?
int
main(void)
{
? ? pid_t ? pid;
?
? ? if ((pid = fork()) < 0) {
? ? ? ? err_sys("fork error");
? ? } else if (pid == 0) {? ? ? /* first child */
? ? ? ? if ((pid = fork()) < 0)
? ? ? ? ? ? err_sys("fork error");
? ? ? ? else if (pid > 0)
? ? ? ? {
? ? ? ? ? ? exit(0);? ? /* parent from second fork == first child */
? ? ? ? }
?
? ? ? ? /*
?? ? ? ? * We're the second child; our parent becomes init as soon
?? ? ? ? * as our real parent calls exit() in the statement above.
?? ? ? ? * Here's where we'd continue executing, knowing that when
?? ? ? ? * we're done, init will reap our status.
? ? ? ? ?*/
? ? ? ? sleep(2);
? ? ? ? printf("second child, parent pid = %ld/n", (long)getppid());
? ? ? ? exit(0);
? ? }
?
? ? if (waitpid(pid, NULL, 0) != pid) ? /* wait for first child */
? ? ? ? err_sys("waitpid error");
?
? ? /*
?? ? * We're the parent (the original process); we continue executing,
?? ? * knowing that we're not the parent of the second child.
?? ? */
? ? exit(0);
}
執(zhí)行結(jié)果:
結(jié)果分析:
在這里我們fork了兩次,原因是,當(dāng)我們想fork一個(gè)子進(jìn)程出來,而我們不希望父進(jìn)程阻塞在wait函數(shù),并且不希望由于父進(jìn)程沒有調(diào)用wait函數(shù)先退出導(dǎo)致子進(jìn)程成為僵尸進(jìn)程,那么fork兩次,并且退出第一個(gè)子進(jìn)程,可以使得父進(jìn)程及時(shí)退出,并且第二個(gè)子進(jìn)程的父進(jìn)程變成init進(jìn)程。
?
小結(jié)本篇主要介紹了fork、vfork、僵尸進(jìn)程、wait和waitpid函數(shù),這些在unix環(huán)境中都是很重要的概念和函數(shù),并且在面試中也經(jīng)常問到。
下一篇的內(nèi)容包括:
?
參考資料:
《Advanced Programming in the UNIX Envinronment 3rd》
?
新聞熱點(diǎn)
疑難解答
圖片精選