【Linux】关于理解fork()函数的简单例⼦
1.fork()函数
fork()是⼀个系统调⽤,⽤于创建进程。创建的这个进程与原来进程⼏乎完全相同。这个新产⽣的进程称为⼦进程。⼀个进程调⽤
fork()函数后,系统先给新的进程分配资源,例如存储数据和代码的空间。然后把原来的进程的所有值都复制到新的新进程中,只有少数值与原来的进程的值不同。相当于克隆了⼀个⾃⼰。需要注意的⼀点:就是调⽤fork之后,两个进程同时执⾏的代码段是fork函数之后的代码,⽽之前的代码已经由⽗进程执⾏完毕。下⾯来看⼀个很简单的例⼦。
fork()返回两个值
返回⼀个⼤于0的值给⽗进程
返回0给⼦进程
返回其他值说明fork失败了
2.关于fork的⼀个简单例⼦
#include<stdio.h>
#include<unistd.h>
int main()
{
pid_t pid;
int count = 0;
pid = fork(); //fork⼀个进程
if(pid == 0) {              //pid为0,
printf("this is child process, pid is %d\n",getpid());//getpid返回的是当前进程的PID
count+=2;
printf("count = %d\n",count);
} else if(pid > 0) {
printf("this is father process, pid is %d\n",getpid());
count++;
printf("count = %d\n",count);
} else {
fprintf(stderr,"ERROR:fork() failed!\n");
}
return 0;
}
下⾯是运⾏结果:
  有⼈可能会对这个运⾏结果产⽣⼀种错觉,就是程序中if语句的两条分⽀if(pid == 0)和else if(pid > 0)都得到了执⾏。其实完全不是这么回事,出现这种运⾏结果的原因是因为,在main()函数调⽤fork了,创建了⼀个新的进程,这个进程称为原来进程的⼦进程。⼦进程与原来的进程并发执⾏,谁先谁后没有规律,由操作系统调度决定。
  我们⽤gdb⼯具对这个程序单步执⾏调试⼀下,可能会对这个过程了解的更清晰⼀些。
3.使⽤gdb调试⽗进程。
1.输⼊gdb a.out然后输⼊start开始调试,此时终端显⽰即将执⾏的代码
2.输⼊n,执⾏当前⼀⾏代码,同时显⽰下⼀条将执⾏的代码
即将创建⼀个⼦进程,当前进程为⽗进程。
3.再输⼊n执⾏pid=fork()语句
这个时候,终端上显⽰
Detaching after fork from child process 2755.
this is child process, pid is 2755
count = 2
这个时候,说明已经新建了⼀个⼦进程,⼦进程PID是2755,⽽且由于我们现在单步调试的是⽗进程,并不影响⼦进程的执⾏。这个⼦进程只有⼏⾏代码,这个时候已经执⾏完了,并且在终端上显⽰了执⾏结果,就是下⾯两⾏内容。
this is child process, pid is 2755
linux下的sleep函数count = 2
4. 输⼊p pid看⼀下fork函数返回给⽗进程的值是不是⼦进程的PID
果然就是⼦进程的PID值。
5.输⼊n接着执⾏判断语句
由于pid的值为2755,因此跳过了if(pid==0)分⽀内的语句,转⽽判断pid是否⼤于0
6.输⼊n接着判断pid是否⼤于0
pid的值⼤于0,执⾏分⽀内的语句。
7.接着输⼊n,直到程序正常结束
上⾯是⽗进程的调试过程,其实⼦进程也可以⽤gdb来调试,下次再说。
4.使⽤ps aux命令查看⽗进程和⼦进程
ps aux命令可以查看系统中正在运⾏的所有进程,不过我们这个例⼦代码很少,系统瞬间就能执⾏完毕,⽤ps aux命令根本捕捉不到。因此我们在代码中做⼀些修改。
#include<stdio.h>
#include<unistd.h>
int main()
{
pid_t pid;
int count = 0;
pid = fork(); //fork⼀个进程
if(pid == 0) {              //pid为0,
printf("this is child process, pid is %d\n",getpid());
count+=2;
printf("count = %d\n",count);
}  else if(pid > 0) {
printf("this is father process, pid is %d\n",getpid());
count++;
printf("count = %d\n",count);
} else {
fprintf(stderr,"ERROR:fork() failed!\n");
}
sleep(10);//新加⼊的⾏,让程序在这⾥暂停10秒,⽗进程和⼦进程都会执⾏这⾏代码
return 0;
}
我们在第30⾏加⼊了⼀条语句,让程序暂停10s。重新编译程序,然后执⾏程序,输⼊./a.out后,快速切换到另外⼀个终端(如果你⼿速慢的话,多暂停⼀会⼉就可以),输⼊ps aux查看正在运⾏的进程。
执⾏程序:
切换终端,输⼊ps aux查看进程
可以看到a.out程序产⽣了两个进程,⽗进程PID是2928,⼦进程PID是2929。

版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。