首先我们来介绍一下fork函数的创建,他引用了#include<unistd.h>这个头文件,用pid_t fork(void)进行创建。下面来介绍几种结束进程的方法:
fork函数的特点是调用一次返回两次。子进程返回0,父进程返回子进程的ID。
为什么父子进程会这样返回呢?
子进程返回0的理由是:一个进程只有一个父进程,所以子进程总是可以通过调用getppid()来访问父进程的ID,另外,进程ID 0 总是由内核交换进程使用,所以一个子进程的进程ID不可能为0。
父进程返回子进程ID的理由是:一个进程可以有多个子进程,但是没有一个函数可以返回其所有子进程的ID。
这里还涉及到printf输出缓冲区的问题。输出时先放在缓冲区,遇到下面四种情况才会输出:
1、遇到“\n”;
2、fflush(stdout);
3、程序结束(exit或return);
4、缓冲区满。
下面介绍两种有无换行符的函数输出结果的区别
(1)有换行符冲洗时
void main()
{
int i=0;
for(;i<2;i++)
{
if(fork())
printf("A\n");
else
printf("B\n");
}
}
运行结果为AABBAB
但是这个结果不是固定的,如果多次执行,会出现不同的结果,但是结果总会是3个A,3个B。调用fork后父子进程谁先执行与操作系统的进程调度算法和当前计算机的环境相关。
这个函数的实现过程为
(1)没有换行符冲洗时
void main()
{
int i=0;
for(;i<2;i++)
{
if(fork())
printf("A");
else
printf("B");
}
}
运行结果为4个A,4个B
下面的运行过程我们用二叉树的形式来表示
由上图所见,当i=0时,创建一个父进程和一个子进程,这时由于没有换行符,所以父进程输出的A与子进程输出的B保存在缓存区不输出,当i=1时,新创建的子进程复制父进程时连缓存区也一起复制过去,然后再相应的输出A、B。