关于创建一个子进程,我们通常使用fork,在一个父进程中,执行pid = fork();,可以根据其返回的值的不同,来判断处于父进程还是子进程,其返回值有三种,如下
负值:创建子进程失败。
零:说明是新创建的子进程。
正值:说明是父进程,并且该值就是新创建的子进程的进程ID
我们创建一个子进程不仅可以用fork还可以使用vfork
虽然fork与vfork两者都用于创建一个子进程,但又有些区别,本文主要指出fork与vfork在创建进程的时候的异同
用一句简短的话来总结这两者的区别,fork是复制于父进程、vfork是共享于父进程
详细如下:
fork函数复制一个父进程的副本,从而拥有独立的代码段,数据段以及堆栈,既称为一个独立的实体,而vfork是共享父进进程的代码以及数据段。并且,fork在执行父子进程的顺序是随机的,而vfork在执行父子进程时,一定是先执行子进程,再执行父进程
首先来看fork
拿fork举一个例子:
#include<stdio.h>
#include<unistd.h>
#include<sys/types.h>
int main()
{
int a = 5;
pid_t pid = -1;
//创建进程
//返回值:失败返回-1,成功0是子进程,>0是父进程
pid = fork();
if(pid < 0)
{
perror("fork error");
return -1;
}
else if(0 == pid)
{
printf("此处是子进程");
a = a+2;
printf("a = %d\n",a);
}
else
{
printf("此处是父进程");
a = a+3;
printf("a = %d\n",a);
}
return 0;
}
注意看a的值的输出,运行结果如下:
分析:
我们在创建一个子进程之前定义了一个变量a,并赋予这个变量初值为5,这个变量首先是属于父进程的(在fork之前)。
在使用了fork函数之后,子进程被创建,他复制了父进程中的a这个变量,以及他的值,注意是复制。
然后,在后面的操作中,子进程中被加了2,父进程中被加了3,可以看到的结果是,两次输出的结果并没有关联,是分别对两个独立的a进行了各自的操作。
我们再来看vfork
也使用一个例子来说明:
#include<stdio.h>
#include<unistd.h>
#include<sys/types.h>
#include<stdlib.h>
int main()
{
int a = 5;
pid_t pid = -1;
//创建进程
//返回值:失败返回-1,成功0是子进程,>0是父进程
pid = vfork();
if(pid < 0)
{
perror("vfork error");
return -1;
}
else if(0 == pid)
{
printf("此处是子进程");
a = a+2;
printf("a = %d\n",a);
exit(0);
}
else
{
printf("此处是父进程");
a = a+3;
printf("a = %d\n",a);
exit(0);
}
return 0;
}
运行结果:
分析:
首先,一点要说明的是,在使用vfork时,子进程必须进行exit进程退出,才能进父进程,另外,可以发现的是,在子进程中对a做出的改变在父进程中有体现,这也证实了vfork创建的子进程是与父进程资源共享的