您的位置:首页 > 其它

进程学习(一)——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
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息