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

43 篇文章 0 订阅
21 篇文章 0 订阅

在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。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值