多语言展示
当前在线:896今日阅读:167今日分享:16

main中调用了vfork后 return和exit的区别

main中调用了vfork后,最后main return时发生crash原因分析:主要就是子进程调用return后,父进程再调用return后,系统做善后工作发现相关资源已经没了(子进程retrun时已经释放了),从而跑飞了【来自知乎和碰到实际问题的理解】
方法/步骤
2

return 和 exit 的区别上面已经讲得很清楚了,system call 和 function call 的区别。至于为什么两个一起return 不行,我的理解是这样的:vfork 的child process 和 parent process 是共享一切资源,memory and stack,并且parent process要等到child process exit之后才会继续。所以如果child process直接return, 等同于parent proces return,当然是没有什么问题的。但是如果parent process 再次return, 系统就迷惑了。vfork(), just like fork(2), creates a child process of the calling process. For details and return value and errors, see fork(2).vfork() is a special case of clone(2). It is used to create new processes without copying the page tables of the parent process. It may be useful in performance-sensitive applications where a child is created which then immediately issues anexecve(2).vfork() differs from fork(2) in that the calling thread is suspended until the child terminates (either normally, by calling_exit(2), or abnormally, after delivery of a fatal signal), or it makes a call to execve(2). Until that point, the child shares all memory with its parent, including the stack. The child must not return from the current function or call exit(3), but may call_exit(2).http://linux.die.net/man/2/vfork

3

更多的解读:首先说一下fork和vfork的差别:fork  是 创建一个子进程,并把父进程的内存数据copy到子进程中。vfork是 创建一个子进程,并和父进程的内存数据share一起用。这两个的差别是,一个是copy,一个是share。你 man vfork 一下,你可以看到,vfork是这样的工作的,1)保证子进程先执行。2)当子进程调用exit()或exec()后,父进程往下执行。那么,为什么要干出一个vfork这个玩意?  原因是这样的—— 起初只有fork,但是很多程序在fork一个子进程后就exec一个外部程序,于是fork需要copy父进程的数据这个动作就变得毫无意了,而且还很重,所以,搞出了个父子进程共享的vfork。所以,vfork本就是为了exec而生。为什么return会挂掉,exit()不会?从上面我们知道,结束子进程的调用是exit()而不是return,如果你在vfork中return了,那么,这就意味main()函数return了,注意因为函数栈父子进程共享,所以整个程序的栈就跪了。如果你在子进程中return,那么基本是下面的过程:子进程的main() 函数 return了而main()函数return后,通常会调用 exit()或相似的函数(如:exitgroup())这时,父进程收到子进程exit(),开始从vfork返回,但是尼玛,老子的栈都被你干废掉了,你让我怎么执行?(注:栈会返回一个诡异一个栈地址,对于某些内核版本的实现,直接报“栈错误”就给跪了,然而,对于某些内核版本的实现,于是有可能会再次调用main(),于是进入了一个无限循环的结果,直到vfork 调用返回 error)好了,现在再回到 return 和 exit,return会释放局部变量,并弹栈,回到上级函数执行。exit直接退掉。如果你用c++ 你就知道,return会调用局部对象的析构函数,exit不会。(注:exit不是系统调用,是glibc对系统调用 _exit()或_exitgroup()的封装)可见,子进程调用exit() 没有修改函数栈,所以,父进程得以顺利执行。

推荐信息