fork()和vfork()函數

fork是一個很重要的函數,能否徹底理解父子進程的關係,取決於你對fork的理解的程度。

#include<unsitd.h>
pid_t fork(void)

從書上我總結了三點:

  1. fork調用一次返回兩次,子進程返回0,父進程返回子進程ID

  2. 父子進程共享正文段,擁有父進程數據段,堆和棧的副本

  3. 對於第二點的父進程的數據段,堆,棧,fork採用一種寫時複製技術,需要的時候才複製一個副本

看一個如下的程序:

#include <apue.h>
int glob = 6;
char buf[] = "a write to stdout";
int main(int argc, char *argv[])
{	
	int var;
	pid_t pid;
	var = 88;
	if(write(STDOUT_FILENO,buf,sizeof(buf)-1) != sizeof(buf)-1)
		err_sys("write error");
	printf("brfore fork\n");
	if((pid = fork()) < 0)
		err_sys("fork error\n");
	else if(pid == 0)
	{
		glob++;
		var++;
	}
	else
		sleep(2);
	printf("pid=%d,ppid=%d,glob=%d,var=%d\n",getpid(),getppid(), glob, var);
	exit(0);

}

vfork函數:

#include <sys/types.h>
#include <unistd.h>
pid_t vfork(void);

vfork:createa child process and block parent

1.vfork的目的是exec一個新程

2.vfork保證子進程先運行,在它調用execexit之後父進程纔可能被調度運行

看一個程序:

#include <apue.h>
int glob = 6;
int main(void)
{
    int var = 88; 
    pid_t pid;
    printf("before vfork\n");
    if((pid = vfork())<0)
        err_sys("vfork error");
    else if(pid == 0)
    {   
        glob++;
        var++;
        printf("before parent!\n");
        _exit(0);
    }   
    /*parent continue here*/

    printf("pid=%d,ppid=%d,glob=%d,var=%d\n",getpid(),getppid(),glob,var);
    exit(0);
}

接下來,我們在理解另外兩個概念:

init進程:

進程ID1,在系統自舉過程結束時由內核調用,該進程不會終止

如果一個進程的父進程已經終止,那麼該進程會被init進程領養

殭屍進程:

一個已經終止,但是其父進程尚未對其處理的進程

看一個程序:

#include <apue.h>
#include <sys/wait.h>

int main(void)
{
    pid_t pid;
    if((pid=fork()) < 0)
        err_sys("fork error\n");
    else if(pid == 0)
    {   
        if((pid=fork()) < 0)
            err_sys("fork error");
        else if(pid > 0)
        {   
    
            printf("first child pid=%d ppid=%d\n",getpid(),getppid());
            exit(0);
        }   

        sleep(2);
        printf("seccond child,parent pid=%d\n",getppid());
        printf("second child pid=%d\n",getpid());
        exit(0);
    }
    if(waitpid(pid,NULL,0) != pid)
        err_sys("waitpid error\n");
    printf("parent pid=%d ppid=%d\n",getpid(),getppid());
    exit(0);
}

這個程序融合了上面的兩個概念:

  1. 這個程序調用了fork兩次,且第二次使第一個子進程終止了,父進程調用了waitpid(由於受到子進程終止時,內核發送的SIGCHILD信號而調用),所以第一進程不會成爲殭屍進程

  2. 第二個子進程在它的父進程終止後會被init進程領養




發佈了39 篇原創文章 · 獲贊 7 · 訪問量 5萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章