linux之return和exit引发的大问题(vfork和fork)

在coolshell.cn上看到的一个问题。为此拿来研究一下。
首先 看看return和exit的差别
在linux上分别跑一下这个代码

int main()
{
    return 0;
    //exit(0);
}

return 0
这里写图片描写叙述
exit(0)
这里写图片描写叙述
这里写图片描写叙述
return在返回时会对栈进行操作,将栈清空。然后跳转到调用函数的下一条指令。而exit没有对栈操作。详细exit怎么执行。会在linux0.12内核里面研究。
看看以下一段代码

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
int main(void) {
    int var;
 int pid;
    var = 88;
    if ((pid = vfork()) < 0) {
        printf("vfork error");
        exit(-1);
    } else if (pid == 0) { /* 子进程 */
        var++;
        return 0;
    }
    printf("pid=%d, var=%d\n", getpid(), var);
    return 0;
}

执行之后
这里写图片描写叙述
非常难想象
假设将return 换成 exit
这里写图片描写叙述
就执行正常。

奇妙的非常。为此分析一下。

在看看使用的这个函数vfork
假设改成fork会是什么样

例如以下
fork+exit
这里写图片描写叙述
执行正常

fork+return
这里写图片描写叙述
也是能够正常执行的,
所以还要研究一下fork和vfork

man fork
Historic description
Under Linux, fork(2) is implemented using copy-on-write pages, so the
only penalty incurred by fork(2) is the time and memory required to
duplicate the parent’s page tables, and to create a unique task
structure for the child. However, in the bad old days a fork(2)
would require making a complete copy of the caller’s data space,
often needlessly, since usually immediately afterward an exec(3) is
done. Thus, for greater efficiency, BSD introduced the vfork()
system call, which did not fully copy the address space of the parent
process, but borrowed the parent’s memory and thread of control until
a call to execve(2) or an exit occurred. The parent process was
suspended while the child was using its resources. The use of
vfork() was tricky: for example, not modifying data in the parent
process depended on knowing which variables were held in a register.
有两点比較重要
1、
the vfork()
system call, which did not fully copy the address space of the parent
process, but borrowed the parent’s memory and thread of control until
a call to execve(2) or an exit occurred.
2、
The parent process was
suspended while the child was using its resources.
也就是vfork是和父进程共享内存的,这里包含栈空间。当调用execve或者exit才会停止这样的共享,而且父进程在子进程执行时是挂起的。
试验一下
測试fork是不是copy_on_write,而且两个进程是同一时候执行的
改动为
这里写图片描写叙述
执行结果为
这里写图片描写叙述
能够看出。var两个进程不共享,且两个进程执行并无先后顺序
相同上面那段代码,再改动为 vfork

执行
这里写图片描写叙述
始终是son先执行,然后exit之后父进程再执行,而且父进程执行时。依然共享var的值

所以到此这个问题也就能够就是了

vfork是子进程共享父进程栈。而return指令是清空栈。返回调用main的函数。而exit不会清理栈的内容。
子进程通过return返回后。父进程会去执行,而此时栈里面已经清空。所以会出问题。


为什么会出项执行多次父进程。网上有人讲,是有的os会又一次调用main。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值