#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
int main(void) {
pid_t pid;
printf("PID before fork():%d\n", getpid());
pid = fork();
if (pid == 0)
printf("This is the child process.my PID:%d,parentPID:%d\n",\
pid, getpid());
else if(pid > 0)
printf("This is the parent process.my PID:%d,childPDI:%d\n",\
getpid(), pid);
else {
printf("fork error.\n");
exit(1);
}
return 0;
}
刚开始学习进程的时候,一直不理解进程的运行过程到底是怎样的。不清楚fork函数的作用,第一篇参考资料的那个例子让我理解的比较清楚了:[cpp] view plain copy
#include <stdlib.h>
#include <stdio.h>
#include <sys/types.h>
#include <unistd.h>
int main(void) {
pid_t pid;
int count = 0;
pid = fork();
printf("This is first,PID:%d.\n", pid);
count++;
printf("count=%d\n", count);
if (pid < 0) {
printf("fork failed.\n");
exit(1);
}
else if (pid == 0)
printf("this is the child process.\n");
else
printf("this is the parent process.child PID:%d.\n", pid);
printf("this is second,PID:%d.\n", pid);
return 0;
}
实际上调用fork函数后分裂出了两个进程,而且它们分别执行互不干扰。一般情况下调用fork函数后父子进程谁先执行是未定的,取决于内核所使用的调度算法。从程序的结果就可以看出来,调用fork函数的部分确实执行了两遍,但是count的值一直都没有改变,这是因为父进程和子进程是分别执行的。
vfork()函数头文件:#include <unistd.h>函数原型:pid_t vfork(void);vfork函数也是创建进程的,但是它实际上也是调用了fork函数。调用vfork与调用fork的作用基本相同,但是差别还是挺大的。先看看下面两个例子:例子1:调用fork函数[cpp] view plain copy
#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <unistd.h>
int globalVal = 5;
int main(void) {
pid_t pid;
int val = 1, i;
pid = fork();
if (pid == 0) {
i = 3;
while (i-- > 0) {
printf("child process is running.\n");
globalVal++;
val++;
sleep(1);
}
printf("child's globalVal = %d, val = %d.\n", globalVal, val);
}
else if (pid > 0) {
i = 5;
while (i-- > 0) {
printf("parent process is running.\n");
globalVal++;
val++;
sleep(1);
}
printf("parent glovalVal = %d, val = %d.\n", globalVal, val);
}
else {
printf("fork failed.\n");
exit(1);
}
return 0;
}
测试结果:
例子2:调用vfork函数[cpp] view plain copy
#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <unistd.h>
int globalVal = 5;
int main(void) {
pid_t pid;
int val = 1, i;
pid = vfork();
if (pid == 0) {
printf("子进程开始了!!!\nn");
i = 3;
while (i-- > 0) {
printf("child process is running.\n");
globalVal++;
val++;
sleep(1);
}
printf("child's globalVal = %d, val = %d.\n", globalVal, val);
printf("子进程结束了!!!\nn");
exit(0);
}
else if (pid > 0) {
printf("父进程开始了!!!\n");
i = 5;
while (i-- > 0) {
printf("parent process is running.\n");
globalVal++;
val++;
sleep(1);
}
printf("parent glovalVal = %d, val = %d.\n", globalVal, val);
printf("父进程结束了!!!\n");
}
else {
printf("fork failed.\n");
exit(1);
}
return 0;
}
测试结果:
从两个程序的测试结果可以看出几点区别来:
调用vfork时,父进程被挂起,子进程运行完exec函数簇的函数或调用exit时解除父进程的挂起状态(要不然会进入死循环,开始我就是按照第一篇资料里那样,在子进程和父进程结束的后面什么都没有加结果进入死循环了,资料里是在父进程结束时调用了exit(0)个人感觉不是这样的,因为正常的情况是先执行子进程然后执行exit(0)结束子进程,接着就会执行父进程,然后父进程执行完了以后就会正常结束程序)。
vfork和fork还有一点不同的就是,调用vfork生成的子进程并不完全复制父进程的数据段,而是和父进程共享数据段。所以globalVal和val变量在子进程之后得到的值,进入父进程继续增加。
调用vfork对于父进程的执行次序还是有限制的。
vfork和for分别与exec函数簇看了些资料,上面都说vfork函数通常是与exec函数簇一起使用的,用来创建执行另一个程序的新进程。由于数据共享的原因fork创建的进程只是父进程的一个副本,也可以利用exec函数在子进程中重新载入一个全新的进程,下面看看fork和vfork分别与exec结合的例子例子1:fork与exec[cpp] view plain copy
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
int main(void) {
pid_t pid = fork();
switch(pid) {
case 0:
printf("子进程\n");
execl("/bin/ls", "ls", "-l", NULL);
break;
case -1:
printf("fork失败\n");
exit(1);
break;
default:
wait(NULL);
printf("完成了\n");
exit(0);
break;
}
return 0;
}
测试结果:
例子2:vfork与exec函数[cpp] view plain copy
#include <stdlib.h>
#include <stdio.h>
#include <unistd.h>
#include <sys/types.h>
int main(void) {
pid_t pid = vfork();
if (pid == 0) {
printf("This is the child process.\n");
execl("/bin/ls", "ls", "-l", NULL);
}
else if (pid > 0) {
wait(NULL);
printf("This is the parent process.\n");
}
else {
printf("vfork failed\n");
exit(1);
}
return 0;
}
测试结果: