fork常用的使用场景在网络服务进程中最常见,父进程等待客户端的服务请求,当请求到达时,父进程调用fork使子进程处理此请求,父进程继续等待下一个服务请求,通过fork创建的进程被称为子进程,该父子进程有如下特点:
1. 子进程获得父进程数据空间,堆栈的副本,父子进程并不共享这些存储空间,因为使用了“写时复制”技术,所以当在写时才会制作相应的副本,其它只读默认是同一份副本
2. 共享正文段
3. 共享在fork父进程打开过的fd
使用时需要注意的点是
父进程在子进程还没退出时就已经先退出,子进程退出了但父进程并没有主动区获取终止进程的有关信息,这时候子进程将会成为僵尸进程(对于一个已经终止,但是其父进程尚未对其进行善后处理(获取终止子进程的有关信息,释放它仍占用的资源)的进程称为僵尸进程)
下面代码演示了简单创建一个子进程的过程
#include <stdio.h>
#include <unistd.h>
#include <sys/types.h>
int globvar = 20; /*external variable in initialized data*/
void main(void)
{
int var; /*automatic variable on the stack*/
pid_t pid;
var = 88;
if (0 > (pid = fork()))
{
printf("fork error\n");
return;
}
else if (0 == pid)
{
printf("I am child process pid = %ld\n", (long)getpid());
globvar++;
var++;
}
else
{
printf("I am parent process pid = %ld\n", (long)getpid());
sleep(2);
}
printf("pid = %ld, glob = %d, var = %d\n", (long)getpid(), globvar, var);
return;
}
编译及运行结果如下
mcchen@mcchen-virtual-machine:/home/samba/share/mywork/test/fork$ gcc -o fork fork.c
mcchen@mcchen-virtual-machine:/home/samba/share/mywork/test/fork$ ./fork
I am parent process pid = 3645
I am child process pid = 3646
pid = 3646, glob = 21, var = 89
pid = 3645, glob = 20, var = 88
从上面运行的结果看:父进程和子进程共享代码段,但是对数据段,栈是独立的,不共享这些存储空间
下一节会讲下僵尸进程的产生和规避