【Linux 编程】vfork
vfork用于创建一个新进程,而该进程的目的就是exec一个新程序。vfork和fork均创建一个子进程,但是vfork并不将父进程的地址空间完全复制到子进程中,因为子进程会调用exec(或exit),于是也就不会访问改地址空间。在子进程调用exec或exit之前,它继续在父进程的空间中运行。
vfork和fork之间的另一个区别:vfork保证子进程先运行。在子进程调用exec或exit之后,父进程才可能被调度运行。
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 #include <stdlib.h> 2 #include <unistd.h> 3 #include <sys/types.h> 4 #include <stdio.h> 5 6 int global = 6; 7 8 int main() 9 { 10 int var; 11 pid_t pid; 12 13 var = 88; 14 printf("before vfork\n"); 15 printf("pid = %d, global = %d, var = %d\n", getpid(), global, var); 16 17 if ((pid = vfork()) < 0) 18 { 19 perror(" failed to vfork()!\n"); 20 return -1; 21 } 22 else if (pid == 0) 23 { 24 printf(" After vfork, and in child process:\n"); 25 printf(" pid = %d, global = %d, var = %d\n", getpid(), global, var); 26 27 global++; 28 var++; 29 _exit(0); 30 } 31 32 printf("\n\nAfter vfork, and in parent process:\n"); 33 printf(" pid = %d, global = %d, var = %d\n", getpid(), global, var); 34 35 return 0; 36 }
运行结果:
利用exec函数以执行一个程序。当进程调用一种exec函数时,该进程执行的程序完全替换为新进程,而新程序则从其main函数开始执行。不改变进程的ID,exec只是用一个全新的程序替换了当前进程的正文、数据、堆和栈段。
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 /* gcc echoall.c -o echoall */ 2 #include <stdlib.h> 3 #include <stdio.h> 4 5 int main(int argc, char **argv) 6 { 7 int i; 8 char **ptr; 9 extern char **environ; 10 11 for (i = 0; i < argc; ++i) 12 printf(" argv[%d]: %s\n", i, argv[i]); 13 14 exit(0); 15 }
将改程序编译结果放置在/home/sunday/share/目录中。
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 /* execDemo.c */ 2 #include <unistd.h> 3 #include <stdio.h> 4 #include <sys/types.h> 5 6 int main() 7 { 8 pid_t pid; 9 10 if ((pid = fork()) < 0) 11 { 12 printf(" fork error!\n"); 13 return -1; 14 } 15 else if (pid == 0) 16 { 17 printf(" Now in child process\n"); 18 printf(" And not leave parent room\n"); 19 if (execl("/home/sunday/share/echoall", "echoall", "myarg1", 20 (char *) 0) < 0) 21 { 22 printf(" execle failed!\n"); 23 return -1; 24 } 25 } 26 27 printf(" Now in parent process\n"); 28 return 0; 29 }
运行结果: