创建进程-fork()和vfork()
1.fork()函数
fork函数返回两次;父进程会返回子进程的ID,子进程的则为0;
#include<sys/types.h>
#include<unistd.h>
#include<stdio.h>
#include<stdlib.h>
int main(){
pid_t pid;
printf("Process Creation Study\n");
pid=fork();
switch(pid){
case 0:printf("Child process is running,chilpid is %d,Parentid id %d\n",pid,getppid());break;
case -1:perror("create failed\n");break;
default:printf("Parent process is running,chilpid is %d,parendid id %d\n",pid,getpid());break;
}
exit(0);
}
可以看到switch被执行了两次,一次在父进程,一次在子进程
2.孤儿进程
如果一个子进程的父进程先于子进程结束,子进程就成为一个孤儿进程,它由init进程收养,成为init进程的子进程。
#include<sys/types.h>
#include<unistd.h>
#include<stdio.h>
#include<stdlib.h>
int main(){
pid_t pid;
pid=fork();
switch(pid){
case 0:
while(1){
printf("A backgroud process,PID %d,ParentPID %d\n",getpid(),getppid());
sleep(3);
}
case -1:
perror("create failed\n");exit(-1);
default:
printf("i am Parent process,pid is %d\n",getpid());
exit(0);
}
return 0;
}
可以看到调用fork函数,父进程执行打印ID号,打印出消息后,父进程被回收,此后子进程变成了孤儿进程,有init收养,此时父进程ID变成1163
3.vfork函数
**相同:**vfork函数和fork函数一样都是调用一次返回两次。
不同:运行以下代码
#include<sys/types.h>
#include<unistd.h>
#include<stdio.h>
#include<stdlib.h>
int globV=5;
int main(){
pid_t pid;
int var=1,i;
pid=vfork();
//pid=fork();
switch(pid){
case 0:
i=3;
while(i-->0){
printf("childprocess is running\n");
globV++;
var++;
sleep(1);
}
printf("childprocess globv=%d,var=%d\n",globV,var);
break;
case -1:
perror("create failed\n");exit(0);
default:
i=5;
while(i-->0){
printf("parentprocess is running\n");
globV++;
var++;
sleep(1);
}
printf("parentprocess globv=%d,var=%d\n",globV,var);
exit(0);
}
}
(1)fork创建一个子进程时,子进程只是完全复制父进程的资源,这样得到的子进程独立于父进程,具有良好的并发性。
用fork()创建时子进程使变量增3,父进程增5,说明子进程有自己独立的空间
使用vfork创建子进程时,操作系统并不将父进程的地址空间完全复制到子进程,用vfork创建的子进程共享父进程的地址空间。
所以结果为globV=13,var=9,也就是说子进程完全运行在父进程的空间地址上,子进程对该地址空间中任何数据的修改同样为父进程所见。
进程时,操作系统并不将父进程的地址空间完全复制到子进程,用vfork创建的子进程共享父进程的地址空间。
所以结果为globV=13,var=9,也就是说子进程完全运行在父进程的空间地址上,子进程对该地址空间中任何数据的修改同样为父进程所见。
(2)fork子进程和父进程哪个优先运行取决于调度算法,而vfork保证子进程先运行,当它调用exec或exit后父进程才可能被调度运行。