#include <stdio.h>
#include <unistd.h>
int main()
{
int tmp = 5;
pid_t res = fork();
if(res < 0){
//fork失败
perror("fork");
}else if(res == 0){
//该进程为子进程
printf("im child[%d],fasther is %d,tmp is %d.\n",getpid(),getppid(),tmp++);
}else{
//该进程为父进程
printf("im father[%d],tmp is %d.\n",getpid(),tmp++);
}
printf("tmp = %d\n",tmp);
return 0;
}
运行结果:
im father[3128],tmp is 5.
tmp = 6
im child[3129],fasther is 1,tmp is 5.
tmp = 6 相关问题小结:
通过结果很明显的能看出本次调用中,先执行父进程,对应pid为3128,在父进程中tmp++,所以输出为6;关键问题在于子进程,有两个关键点。
①为什么结果中子进程父亲pid为1:通过输出我们能看出父进程先执行完成后才执行的子进程,也就是说当子进程执行时父进程已结束,此时该子进程相当于一个孤儿进程,被pid为1也就是init进程所管理,所以子进程的ppid为1;
②为什么子进程最后输出tmp值还为6: fork进程采用的是写时拷贝,父子进程一开始共享一片内存区域,但是只有有一方要对数据进行修改,则再开辟一块空间,防止相互修改影响。所以在上述代码中,虽说是一个tmp,其实内存中各自保留了一份值。 二、关于fork过程中写时拷贝:
#include <stdio.h>
#include <unistd.h>
int main()
{
int tmp = 5;
printf("there is fork before\n");
pid_t res = fork();
if(res < 0){
//fork失败
perror("fork");
}else if(res == 0){
//该进程为子进程
printf("im child[%d],tmp is %d.\n",getpid(),tmp++);
}else{
//该进程为父进程
printf("im father[%d],tmp is %d.\n",getpid(),tmp++);
}
printf("tmp = %d\n",tmp);
return 0;
}
输出结果:
there is fork before
im father[3625],tmp is 5.
tmp = 6
im child[3626],tmp is 5.
tmp = 6 三、fork调用失败的原因:
①系统中已经存在太多进程,无法再创建新的进程。可通过ulimit -a命令查看当前所有的资源限制。
②内存不足,由于开辟每个新的进程都要分配一个pcb,并为新进程分配资源,内存都不足也就别提还想着再创建进程了。 vfork相关问题: 一、vfork基础了解
<1>vfork创建新进程的主要目的在于用exec函数执行另外的程序,实际上,在没调用exec或_exit之前子进程与父进程共享数据段。在vfork调用中,子进程先运行,父进程挂起,直到子进程调用exec或_exit,在这以后,父子进程的执行顺序不再有限制。
头文件:#include < unistd.h >
函数原型:pid_t vfork( )
返回值:返回值大于0则当前进程为父进程,等于0代表为子进程,小于零代表创建子进程失败。
通过一个例子来了解:
#include <stdio.h>
#include <unistd.h>
int tmp = 3;
int main()
{
pid_t res = vfork();
if(res < 0){
perror("vfork");
_exit();
}else if(res == 0){
tmp = 10;
printf("child res = %d\n",tmp);
_exit(0);
}else{
printf("father res = %d\n",tmp);
}
return 0;
}
输出结果:
child res = 10
father res = 10
结果分析:正如上面所说的,子进程直接公用父进程的页表,改变子进程的数据也会影响到父进程。