【问题标题】:fork() and execve() efficiencyfork() 和 execve() 效率
【发布时间】:2018-07-10 20:00:58
【问题描述】:

就内存分配效率而言,在子代码中的fork() 之后,如果我使用execve() 执行一个程序,这将比没有execve() 执行的同一程序更有效,因为孩子不会分配父亲的堆栈和堆,而只是自己的?

朴素的例子:

没有执行

 [..some father code...]
int i;
if(!fork()) {
 sum() //from an #include "porg.h"
}

使用执行

 [..some father code...]

if(!fork()) {
 execve("sum", NULL, NULL); //sum is a program which executes i=2+3
}

第二个在内存分配方面比较好? 是更好地替换我的进程的整个虚拟地址空间,还是更好地通过调用另一个程序中的函数来运行上述代码,该程序包含在#include“prog”中,就完成的操作数量而言程序执行过程中所携带的内存是怎么回事?

【问题讨论】:

  • 请定义memory 的含义。我将其理解为virtual memory。所以编辑你的问题来改进它。目前还不清楚。如果可能,提供一些minimal reproducible example
  • 这毫无意义 - 执行一个完全不同的程序比执行一条指令更便宜(就 CPU 或内存而言)怎么可能?!毕竟,两个代码 sn-ps 都会调用fork(),而第二个代码的作用要大得多。
  • 请在内存分配效率中定义效率是什么意思。
  • @wallyk 编辑希望它清楚

标签: linux memory heap-memory stack-memory


【解决方案1】:

仔细阅读一些关于 Linux 或 POSIX 编程的书,也许是旧的ALP。另请阅读intro(2)fork(2)execve(2)

在成功的execve 之后,您的process 的整个virtual address space 已被替换并重新初始化,根据执行的ELF 可执行文件(参见elf(5);所以execve 不会返回,除非失败)。

因此,您的 sum 程序看不到执行它的前一个程序的任何内容(除了强制性的 argvenviron,它们被 execve复制)。顺便说一句,您对execve 的使用是错误的。您应该提供一些 argv 数组和一些 environ 数组(两者都应该是非空的,argv 应该是非空的,并且两者都应该以 NULL 字符串结尾)......你经常会更喜欢一些exec*(3) 函数。

fork 成功之后,两个(子和父)进程都有自己的虚拟地址空间(最初,几乎相同的副本)。顺便说一句,您的代码忘记检查 fork 的失败。

在内存分配方面第二个更好?

所以这个问题没有意义。整个“内存”——实际上是虚拟地址空间——已被重置并重新初始化(包括调用堆栈和堆)。

您可以使用/proc/ 探索进程的虚拟地址空间。见proc(5)。尝试cat /proc/$$/mapscat /proc/self/maps 以更好地了解虚拟地址空间。

还可以与strace(1) 一起玩,以了解某些程序或进程所做的system calls。尝试例如strace date(另请参阅this)。

比不使用 execve() 执行的同一个程序

这是不可能的,因为execve唯一执行程序的方式(当然init除外,今天称为systemd - 见@987654336 @,它会在启动时由内核神奇地启动;以及其他一些奇怪的内核启动进程....)

【讨论】:

  • 比没有 execve() 执行的同一程序:对于程序,我的意思是代码对不起,对于内存分配效率,我的意思是:替换我的进程的整个虚拟地址空间更好还是更好通过调用#include“prog”中包含的另一个程序中的函数来运行上述代码,就so的操作数量和程序执行期间所携带的内存而言?跨度>
  • 请编辑您的问题(例如,改进它并提供一些minimal reproducible example),不要评论我的答案。我仍然不明白你的意思(我猜你不明白 forkexecve 做什么,什么是虚拟地址空间或进程)。我不明白什么应该比什么更好
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-09-01
  • 2020-06-18
  • 1970-01-01
相关资源
最近更新 更多