函数fork和vfork
2015-08-03 23:09
507 查看
一.函数fork
一个现有的进程可以调用fork函数创建一个新的进程。
返回值:子进程返回0,父进程返回子进程ID;若出错,返回-1 。
fork函数被调用一次,但返回两次。两次返回的区别是子进程的返回值是0,而父进程的返回值则是新建子进程的进程ID。
将子进程ID返回给父进程的原因是:因为一个进程的子进程可以有多个,并且没有一个函数使一个进程可以获得其所有子进程的进程ID。
fork使子进程得到返回值0的理由是:一个进程只会有一个父进程,所以子进程总是可以调用getppid以获得其父进程的进程ID。
子进程和父进程继续执行fork调用之后的指令。子进程是附近成的副本。子进程获得附近成数据空间,堆和栈的副本。下面一个例子可以看出子进程对变量的修改不影响父进程中该变量的值。
执行此程序得到:
在fork后父进程先执行还是子进程先执行是不确定的。
二.函数vfork
vfork函数的调用序列和返回值与fork相同,但两者的语义不同。
vfork函数用于创建一个新进程,该进程的目的是exec一个新程序。vfork与fork一样都创建一个子进程,但是vfork不将父进程的地址空间完全复制到子进程中,因为子进程会立即调用exec(或exit),于是也就不会引用该地址空间。不过在调用exec或exit之前,它会在父进程的空间中运行。
vfork和fork之间的另一个区别是:vfork保证子进程先运行,在它调用exec或exit之后父进程才能被调度执行。(如果在调用这两个函数之前子进程依赖于父进程的进一步动作,则会导致死锁。)
下面的程序不再需要让父进程调用sleep,因为我们可以保证,在子进程调用exec或exit之前,内核会使父进程处于休眠状态。
#include "apue.h"
#include "myerror.h"
using namespace std;
int globvar=6; //external variable in initialized data
char buf[]="a write to stdout\n";
int main()
{
int var; //automatic value on the stack
pid_t pid;
var=88;
//if(write(STDOUT_FILENO,buf,sizeof(buf)-1)!=sizeof(buf)-1)
//printf("write error");
printf("before fork\n"); //we don't flush stdout
if((pid=fork())<0)
{
//printf("fork error");
err_sys("vfork error");
}
else if(pid==0)
{
globvar++;
var++;
_exit(0);
}
printf("pid=%ld,glob=%d,var=%d\n",(long)getpid,globvar,var);
exit(0);
}
注意:子进程对变量作增1操作,结果改变了父进程中的变量值,这是因为子进程在父进程的地址空间中进行。
一个现有的进程可以调用fork函数创建一个新的进程。
#include <unistd.h> pid_t fork(void);
返回值:子进程返回0,父进程返回子进程ID;若出错,返回-1 。
fork函数被调用一次,但返回两次。两次返回的区别是子进程的返回值是0,而父进程的返回值则是新建子进程的进程ID。
将子进程ID返回给父进程的原因是:因为一个进程的子进程可以有多个,并且没有一个函数使一个进程可以获得其所有子进程的进程ID。
fork使子进程得到返回值0的理由是:一个进程只会有一个父进程,所以子进程总是可以调用getppid以获得其父进程的进程ID。
子进程和父进程继续执行fork调用之后的指令。子进程是附近成的副本。子进程获得附近成数据空间,堆和栈的副本。下面一个例子可以看出子进程对变量的修改不影响父进程中该变量的值。
#include "apue.h" //#include "error.h" using namespace std; int globvar=6; //external variable in initialized data char buf[]="a write to stdout\n"; int main() { int var; //automatic value on the stack pid_t pid; var=88; if(write(STDOUT_FILENO,buf,sizeof(buf)-1)!=sizeof(buf)-1) printf("write error"); printf("before fork\n"); //we don't flush stdout if((pid=fork())<0) { printf("fork error"); } else if(pid==0) //子进程 { globvar++; var++; } else //父进程,使自己休眠2s,从而让子进程进行 sleep(2); printf("pid=%ld,glob=%d,var=%d\n",(long)getpid,globvar,var); exit(0); }
执行此程序得到:
在fork后父进程先执行还是子进程先执行是不确定的。
二.函数vfork
vfork函数的调用序列和返回值与fork相同,但两者的语义不同。
vfork函数用于创建一个新进程,该进程的目的是exec一个新程序。vfork与fork一样都创建一个子进程,但是vfork不将父进程的地址空间完全复制到子进程中,因为子进程会立即调用exec(或exit),于是也就不会引用该地址空间。不过在调用exec或exit之前,它会在父进程的空间中运行。
vfork和fork之间的另一个区别是:vfork保证子进程先运行,在它调用exec或exit之后父进程才能被调度执行。(如果在调用这两个函数之前子进程依赖于父进程的进一步动作,则会导致死锁。)
下面的程序不再需要让父进程调用sleep,因为我们可以保证,在子进程调用exec或exit之前,内核会使父进程处于休眠状态。
#include "apue.h"
#include "myerror.h"
using namespace std;
int globvar=6; //external variable in initialized data
char buf[]="a write to stdout\n";
int main()
{
int var; //automatic value on the stack
pid_t pid;
var=88;
//if(write(STDOUT_FILENO,buf,sizeof(buf)-1)!=sizeof(buf)-1)
//printf("write error");
printf("before fork\n"); //we don't flush stdout
if((pid=fork())<0)
{
//printf("fork error");
err_sys("vfork error");
}
else if(pid==0)
{
globvar++;
var++;
_exit(0);
}
printf("pid=%ld,glob=%d,var=%d\n",(long)getpid,globvar,var);
exit(0);
}
注意:子进程对变量作增1操作,结果改变了父进程中的变量值,这是因为子进程在父进程的地址空间中进行。
相关文章推荐
- Android 实例:通过自定义View组件实现跟随手指移动的小兔子
- 维特比算法在隐马尔可夫模型中的应用
- SpringMVC 文件上传配置,多文件上传,使用的MultipartFile
- SQLite with readline support on Ubuntu
- JNI——Java调用DLL
- hough拟合圆弧
- 维翔主机asp主机使用遇到的问题及解决方案总结
- Tomcat Session 持久化
- java基础知识整理:
- 8.3CSS代码缩写 颜色值
- 关于重装系统后,Windows和Linux双系统只能进入一个的问题
- Android Hotpatch系列之-项目介绍
- 高级ios工程师和初级工程师的区别
- 8月3日所学
- 博客开篇
- 有关tomcat的安装与配置问题
- 4、C语言和设计模式(之原型模式)
- “耍流氓”的代收服务,你们懂什么叫用户体验吗?
- 【背包总结】【交换维度】
- Android推送 百度云推送 入门篇