转自:http://chhaj5236.blog.163.com/blog/static/1128810812013327102727881/
参考资料[1]对vfork进行了较为详细的描述:vfork()函数和fork()一样会创建一个新进程,所不同的是vfork()创建的子进程与父进程共享地址空间,且父进程会被阻塞,直到子进程调用exec()家族的某个函数,或调用_exit()。由于父子进程共享相同的地址空间,(准确地说是子进程)一定不要从调用vfork()的函数中返回,否则会破坏父进程的堆栈。同时,在执行exec()和_exit()之前,也最好不要调用任何对父进程状态有影响的操作,如改变父进程某个变量的值,或使用exit()退出子进程(exit()退出时会关闭I/O缓存,意味着父进程也会失去I/O缓存)等。
本文的主要目的就是理清参考文献[2]中提到的例子,即如果子进程从调用vfork()的函数中返回,会发生什么?为了更加清晰地说明这个问题,将文中提及的代码修改为如下所示:
#include<unistd.h> #include<sys/types.h> #include<stdio.h> #include<stdlib.h> #include<time.h> int createproc(); int main(){ pid_t pid; pid = createproc(); printf("pid: %d, ret_pid: %d\n", getpid(), pid); exit(0); } int createproc(){ pid_t pid; pid = vfork(); printf("after vfork - pid: %d, ret_pid: %d\n", getpid(), pid); if(!pid){ printf("pid: %d, parent: %d\n", getpid(), getppid()); //execl("/bin/ls", "ls", "-l", NULL); //正常情况下,应该调用exec()家族的一个函数,载入新的程序 return pid; } else return -1; }
after vfork - pid: 29327, ret_pid: 0 pid: 29327, parent: 29326 pid: 29327, ret_pid: 0 after vfork - pid: 29326, ret_pid: 29327 after vfork - pid: 29328, ret_pid: 0 pid: 29328, parent: 29326 Segmentation fault
80484d5: e8 2d 00 00 00 call 8048507 <_Z10createprocv>
80484da: 89 44 24 1c mov %eax,0x1c(%esp)
804850e: e8 ad fe ff ff call 80483c0 <vfork@plt>
8048513: 89 45 f4 mov %eax,-0xc(%ebp)
000983f0 <__vfork>:
983f0: 59 pop %ecx
983f1: 65 8b 15 6c 00 00 00 mov %gs:0x6c,%edx
983f8: 89 d0 mov %edx,%eax
983fa: f7 d8 neg %eax
......
9840e: cd 80 int $0x80
98410: 51 push %ecx
......
==============================反汇编代码================================