zoukankan      html  css  js  c++  java
  • 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
    ", 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。

  • 相关阅读:
    新内容记录:
    一个用于提取简体中文字符串中省,市和区并能够进行映射,检验和简单绘图的python模块
    django后台获取相同name名的数据
    python 使用qqwry.dat获取ip物理地址:速度快
    laydate设置起始时间,laydate设置开始时间和结束时间
    评论抓取:Python爬取微信在APPStore上的评论内容及星级
    H5上传压缩图片
    Django自带的加密算法及加密模块
    git入门
    WPF
  • 原文地址:https://www.cnblogs.com/jhcelue/p/7221164.html
Copyright © 2011-2022 走看看