进程学习(一)——fork()和vfork()函数学习过程
2014-06-06 10:50
676 查看
fork()函数:
头文件:#include <unistd.h>函数原型:pid_t for(void);
fork()函数用于派生出另一个进程,原有的进程成为父进程,新生成的进程成为子进程。父进程调用fork后返回值是子进程的ID,子进程调用fork后返回值是0,调用出错时,返回值为-1.下面看个fork函数创建进程的例子:
#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; }
从测试结果可以看出,印证了我们上面说的,父进程返回的是子进程ID,子进程返回的是0.
刚开始学习进程的时候,一直不理解进程的运行过程到底是怎样的。不清楚fork函数的作用,第一篇参考资料的那个例子让我理解的比较清楚了:
#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函数
#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函数
#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
#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函数
#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; }
测试结果:
参考资料: http://www.360doc.com/content/11/0411/19/6580811_108904985.shtml http://www.cnblogs.com/codebean/archive/2011/06/06/2073609.html
相关文章推荐
- Linux 进程学习1 --fork()函数
- UNIX环境编程学习笔记(19)——进程管理之fork 函数的深入学习
- linux c之创建进程fork和vfork函数之间的区别
- UNIX环境编程学习笔记(19)——进程管理之fork 函数的深入学习
- linux进程创建过程与原理 & linux进程创建:fork、vfork和clone联系与区别
- Linux进程函数fork(),vfork(),execX()的深入理解
- UNIX再学习 -- 函数 fork 和 vfork
- 进程创建函数fork和vfork的区别
- UNIX环境编程学习笔记(19)——进程管理之fork 函数的深入学习
- fork()创建子进程步骤、函数用法及常见考点(内附fork()过程图)
- 【经典转载】Linux进程学习系列之二 fork()和vfork()的学习
- 进程创建函数fork()、vfork()
- 进程原语:fork()函数,getpid()函数和getppid()函数,getuid()函数,getgid()函数,vfork()
- Linux基础学习系列:对于fork()函数的学习,及进程创建相关知识
- 4进程原语:fork()函数,getpid()函数和getppid()函数,getuid()函数,getgid()函数,vfork()
- Linux学习之进程fork()与vfork()
- Linux的进程学习笔记之fork与vfork
- fork()创建子进程步骤、函数用法及常见考点(内附fork()过程图)
- 进程创建函数fork()、vfork() ,以及excel()函数
- 进程创建函数fork与vfork