在UNIX/Linux中的fork还没实现copy on write(写时复制)技术之前。Unix设计者很关心fork之后立刻执行exec所造成的地址空间浪费,所以引入了vfork系统调用。其中,vfork子进程与父进程共享数据段,并不真正复制父进程内存,因此在vfork之后执行exec系列函数,并不会导致地址空间浪费以及无用的空间复制时间.而且,即使fork实现了copy on write,效率也没有vfork高.
但是,vfork有个限制,子进程必须立刻执行_exit或者exec系列函数。因此我们不推荐使用vfork,因为几乎每一个vfork的实现,都或多或少存在一定的问题(可以尝试在vfork之后的子进程中既不执行_exit,也不执行exec函数)。
1. fork子进程拷贝父进程的数据段(但是现在提供了写时复制技术,只有当子进程真正需要写内存时,才复制出该内存的一段副本),因此,在父进程/子进程中对全局变量所做的修改并不会影响子进程/父进程的数据内容.
vfork子进程与父进程共享数据段,因此父子进程对数据的更新是同步的;
2. fork父、子进程的执行次序是未知的,取决于操作系统的调度算法
vfork:子进程先运行,父进程后运行;
//在Linux 2.6内核上会持续执行,不会退出! #include <unistd.h> #include <errno.h> #include <stdlib.h> #include <stdio.h> #include <string.h> #include <iostream> using namespace std; int main() { int iNumber = 0; pid_t pid = vfork(); if (pid == -1) { perror("fork"); return -1; } else if (pid > 0) { cout << "In Parent Program..." << endl; cout << "iNumber = " << iNumber << endl; cout << "pid = " << static_cast<int>(getpid()); cout << "\t ppid = " << static_cast<int>(getppid()) << endl; //_exit(0); } else if (pid == 0) { iNumber ++; cout << "In Child Program..." << endl; cout << "iNumber = " << iNumber << endl; cout << "pid = " << static_cast<int>(getpid()); cout << "\t ppid = " << static_cast<int>(getppid()) << endl; //_exit(0); } return 0; }
//如前... int main() { int iNumber = 0; pid_t pid = vfork(); if (pid == -1) { perror("fork"); return -1; } else if (pid > 0) { cout << "In Parent Program..." << endl; cout << "iNumber = " << iNumber << endl; cout << "pid = " << static_cast<int>(getpid()); cout << "\t ppid = " << static_cast<int>(getppid()) << endl; } else if (pid == 0) { iNumber ++; cout << "In Child Program..." << endl; cout << "iNumber = " << iNumber << endl; cout << "pid = " << static_cast<int>(getpid()); cout << "\t ppid = " << static_cast<int>(getppid()) << endl; //将自己写的程序启动起来 execve("./hello",NULL,NULL); _exit(0); } return 0; }
//...如前 int main() { int iNumber = 0; pid_t pid = vfork(); if (pid == -1) { perror("fork"); return -1; } else if (pid > 0) { cout << "In Parent Program..." << endl; cout << "iNumber = " << iNumber << endl; cout << "pid = " << static_cast<int>(getpid()); cout << "\t ppid = " << static_cast<int>(getppid()) << endl; } else if (pid == 0) { iNumber ++; cout << "In Child Program..." << endl; cout << "iNumber = " << iNumber << endl; cout << "pid = " << static_cast<int>(getpid()); cout << "\t ppid = " << static_cast<int>(getppid()) << endl; //将ls命令启动起来,注意:由于C++严格的类型转换机制,需要在字符串前加(char*) char *const args[] = {(char *)"/bin/ls", (char *)"-l", NULL}; int res = execve("/bin/ls",args,NULL); if (res == -1) { perror("execve"); _exit(1); } _exit(0); } return 0; }
原文地址:http://blog.csdn.net/zjf280441589/article/details/41078593