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

linux之return和exit引发的大问题(vfork和fork)的更多相关文章

  1. Linux编程return与exit区别

    Linux编程return与exit区别 exit  是用来结束一个程序的执行的,而return只是用来从一个函数中返回. return return 表示从被调函数返回到主调函数继续执行,返回时可附 ...

  2. return和exit函数的区别

    在上Linux课的时候,老师提到一句,调用vfork产生的子进程就是为了使用exec族函数来执行其他的代码逻辑. 在子进程退出的时候有两种方式,exit和exec族函数,不能使用return,为什么不 ...

  3. 关于return和exit

    关于return和exit 在子进程退出的时候有两种方式,exit和exec族函数,不能使用return,为什么不能用return呢,exit改成return 会出现父子进程又各自重复开始进行. 1. ...

  4. 理解 break, continue, return 和 exit

    你们知道 “break”, “continue”, “return” 和 “exit”的作用吗? 它们是功能强大的语言结构体.下面通过一个测试函数来说明它们之间的不同. 1 2 3 4 5 6 7 8 ...

  5. DevC++ return 1 exit status

    当使用DevC++时编译运行程序出现 return 1 exit status 有可能是因为有在运行的命令窗口未关闭.

  6. Windows下return,exit和ExitProcess的区别和分析

    通常,我们为了使自己的程序结束,会在主函数中使用return或调用exit().在windows下还有ExitProcess()和TerminateProcess()等函数. 本文的目的是比较以上几种 ...

  7. C++中的return和exit区别

    在main函数中,return和exit经常混用,两者的一个区别:return会执行statck unwinding,而exit不会.如果触发了信号,exit也同样不会做stack unwinding ...

  8. oracle 存储过程循环体中的return和exit区别:

    oracle 存储过程循环体中的return和exit区别:   (1) return 跳出整个循环,终止该循环, 后面的不再执行.     相当于 Java 中的break;   (2)  exit ...

  9. return 与 exit() 的区别

    return是一个关键字,返回函数值:exit()是一个函数: return是语言级的:exit()是操作系统提供的函数: return表示函数退出:exit()表示进程退出: 非主函数中调用retu ...

随机推荐

  1. 【Luogu】P3768简单的数学题(杜教筛)

    题目链接 emm标题全称应该叫“莫比乌斯反演求出可狄利克雷卷积的公式然后卷积之后搞杜教筛” 然后成功地困扰了我两天qwq 我们从最基本的题意开始,一步步往下推 首先题面给出的公式是$\sum\limi ...

  2. HDU——2723Electronic Document Security(STL map嵌套set做法)

    Electronic Document Security Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K ( ...

  3. mod性质 学习笔记

    mod性质小结 \(a\equiv b(\mod m)\) $ \rightarrow \( \)a-b=k*m,k\in Z$ \(a\equiv b且c\equiv d(\mod m)\) \(\ ...

  4. Linux System Programming 学习笔记(八) 文件和目录管理

    1. 文件和元数据 每个文件都是通过inode引用,每个inode索引节点都具有文件系统中唯一的inode number 一个inode索引节点是存储在Linux文件系统的磁盘介质上的物理对象,也是L ...

  5. 在vue-cli环境下模拟数据接口及如何应用mockjs

    第一种办法 1.需要先准备json文件 在根目录下新建个oapi文件夹下新建个iorder.json文件将需要遍历的json数据沾里面. 2.在build文件夹下新建dev-server.js 文件 ...

  6. luogu 1327 数列排序 & 2017 ACM-ICPC 亚洲区(南宁赛区)网络赛 J题 循环节

    luogu 1327 数列排序 题意 给定一个数列\(\{an\}\),这个数列满足\(ai≠aj(i≠j)\),现在要求你把这个数列从小到大排序,每次允许你交换其中任意一对数,请问最少需要几次交换? ...

  7. POJ 3468:A Simple Problem with Integers(线段树[成段更新])

    题意:N个数Q次操作.一共两种操作:Q l r :询问[l,r]这个区间里的数字和,C l r c: [l,r]区间里的每个数都加上c.1 ≤ N,Q ≤ 100000. 方法:线段树的成段更新.注意 ...

  8. hdu3338 / 方格横纵和问题终极版,最大流斩

    此题被誉为神奇最大流,诱惑我去做了下,感觉也是通常的思路. 题意:1.用1-9去填,满足所给的行/列和要求(和那个什么游戏差不多...) 求一种合法方案,输出.如:   一看,直接就建图了,每个点在白 ...

  9. LeetCode OJ--Rotate List

    http://oj.leetcode.com/problems/rotate-list/ 取得后面k个节点,然后截断插到前面.如果k比list长,则按照求余算. 去后面的k个节点:使用两个指针,第一个 ...

  10. EXT.JS以下两种写法在初始载入时是一样的效果

    /* Ext.application({ name: 'MyfirstApplication', launch: function () { Ext.Msg.alert("Hello&quo ...