就内存分配效率而言,fork()
在子代代码中的 a 之后,如果我使用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”中,就完成的操作数而言通过 so 以及程序执行期间携带的内存?
答案1
第一个代码片段中的代码if
包含一个添加和一个赋值。这就像任何事情一样简单,它将编译成机器代码中的大约两条指令。
在第二个中,有一堆参数加载并推送到堆栈、函数调用、libc 的一些内部处理,其中涉及将参数移动到系统调用的正确位置,然后是系统调用本身。
系统调用需要切换到内核模式(无论需要什么成本,取决于系统),在内核中查找以查找实际处理的系统调用,然后执行程序sum
。执行程序需要找到包含程序的文件,将其加载到内存中(可能等待磁盘),解释 ELF 标头以了解程序每个部分在内存中的位置,设置一些内存映射(可能是页表)所以...
我想你明白了。
答案2
这样的假设是不对的。分叉子进程和子进程都没有sum
显式地使用堆。但是在 中sum
,C 运行时可能会在程序启动时初始化一些堆结构。堆栈也有类似的可能性。
然而,这是一个值得思考的合理问题。如果父进程在子进程运行时也在修改内存,则子进程将托管所有已修改内存的副本(写入时复制)。通常,孩子正在执行子任务并且仅使用该数据的子集。
对于较大的父进程和运行时间较长的子进程来说,它可能会很重要。