调用 execve() 后,旧的堆栈、堆和(已初始化和未初始化的)数据段会发生什么情况?

调用 execve() 后,旧的堆栈、堆和(已初始化和未初始化的)数据段会发生什么情况?

execve() 的手册页说

execve() 执行文件名指向的程序。这会导致调用进程当前正在运行的程序被新程序替换,其中新初始化的堆栈、堆和(已初始化和未初始化的)数据段。

如果调用进程是由 vfork() 创建的,则意味着exec()为新程序提供了新的地址空间;它不会修改父地址空间。

如果调用进程更一般地由 fork() 创建,那么旧的“堆栈、堆和(已初始化和未初始化的)数据段”通常会发生什么?他们的空间被释放了吗?

execve() 的行为是否取决于调用进程的创建方式?

在看到引用之前,我认为 execve() 会覆盖旧的“堆栈、堆和(初始化和未初始化的)数据段”,而不是创建新的。所以当我看到这句话时,想知道为什么要浪费新空间?

谢谢。

答案1

execve() 的行为是否取决于调用进程的创建方式?

不。

在看到引用之前,我认为 execve() 会覆盖旧的“堆栈、堆和(初始化和未初始化的)数据段”,而不是创建新的。

否:execve() 创建新段并释放旧段。

所以当我看到这句话时,想知道为什么要浪费新空间?

记住,我们正在谈论虚拟内存!

创建空白段仅分配少量物理内存,以跟踪该段。无论段有多大,该分配的大小都是固定的。

必须为写入的每个页分配一个物理页。父进程可能已写入大量页面。但是,如果子进程在运行时只使用了一点堆栈/堆/数据,那么它就没有充分的理由保留对父进程所有脏页的引用!如果父进程退出而子进程继续运行,则会浪费内存。

删除对旧段和旧页面的引用是最有效的方法。因为如果那是仅有的引用该内存,可以释放物理内存。

相关内容