fork函数

来源:互联网 发布:python simyou 编辑:程序博客网 时间:2024/05/18 09:07

一个现有进程可以通过fork函数,即pid_t fork(void),创建新的进程。原进程称为父进程,通过fork函数创建的新进程称为子进程。fork函数调用一次返回两次,在父进程中返回子进程的pid,在子进程中返回0,出错返回-1。 

可以通过getpid()得到进程的pid,通过getppid()得到父进程的pid。产生一个子进程可以在任意时刻通过getppid()得到父进程的pid,但是,不能知道一个父进程的所有子进程的pid,一旦子进程结束,父进程无法得到其pid,这也是父进程中返回其子进程pid的原因。 另外,进程ID 0 总是由内核交换使用,所以一个子进程的pid不可能为0.

子进程在运行而其父进程已经结束,称该子进程为孤儿进程,将其父进程pid设为1(这也就相当于福利院啦)。

接下来看看下面的程序运行的结果。

程序一:

int main(){int i = 0;for(;i<2;++i){if(fork())printf("A %d %d %d\n",i,getppid(),getpid());elseprintf(""B %d %d %d\n",i,getppid(),getpid());}}

为什么会出现这样的结果呢?听我细细道来。

开始时 i = 0 ,程序运行到if调用fork函数,创建新进程3244。在父进程3243中返回子进程pid,即3244,输出A;在进程中返回0,输出B。 接着循环 i = 1 ,这时有两个进程3243和3244都要执行,父进程3243创建子进程3245,分别输出A、B;父进程3244创建子进程3246,再分别输出A、B。 所以运行结果为三个A,三个B。为什么说是“三个A,三个B”而不说“AABBAB”呢?这是因为父子进程fork之后谁先运行与操作系统的进程调度算法和当前计算机运行环境有关,不是确定的顺序。这里还要注意父子进程是相对而言的。

程序二:

int main(){int i = 0;for(;i<2;++i){if(fork())printf("A");elseprintf("B");}}

在程序一的基础上输出时没有“\n”又会出现什么情况呢?

这里主要涉及到printf输出缓冲区的问题。输出时先放在缓冲区,遇到下面四种情况才会输出: 

1、遇到“\n”; 

2、fflush(stdout);

3、程序结束(exit或return); 

4、缓冲区满。 

针对这个程序在程序一基础上分析,如下图所示:

i = 0 时,程序运行到if调用fork函数,创建新进程3244。在父进程3243中返回子进程pid,即3244,将A放在缓冲区;在进程中返回0,将B放在缓冲区。 

i = 1时,两个进程3243和3244都要执行,父进程3243创建子进程3245,父进程缓冲区中的A也被拷贝到子进程中,然后执行进程3243,A被放到缓冲区,结束输出AA,执行进程3245,B被放到缓冲区,结束输出AB;父进程3244创建子进程3246,父进程缓冲区中的B也被拷贝到子进程中,然后执行进程3244,A被放到缓冲区,结束输出BA,执行进程3245,B被放到缓冲区,结束输出BB。

所以该程序共输出四个A,四个B。 

 程序三:

int main(){if(fork() || fork())printf("A\n");elseprintf("B\n");}

其结果如下图所示:

首先调用第一个fork函数,父进程中返回子进程pid,if判断为真就不再判断后边的,输出A;子进程中返回0,接着调用第二个fork函数,返回新的子进程的pid,输出A;新的子进程中返回0,输出B,如下图所示:

这里要注意“||”的判断,例如 条件A||条件B ,如果A为真就不再判断B。


原创粉丝点击