%20%E5%90%8E%EF%BC%8C%E6%97%A7%E7%9A%84%E5%A0%86%E6%A0%88%E3%80%81%E5%A0%86%E5%92%8C%EF%BC%88%E5%B7%B2%E5%88%9D%E5%A7%8B%E5%8C%96%E5%92%8C%E6%9C%AA%E5%88%9D%E5%A7%8B%E5%8C%96%E7%9A%84%EF%BC%89%E6%95%B0%E6%8D%AE%E6%AE%B5%E4%BC%9A%E5%8F%91%E7%94%9F%E4%BB%80%E4%B9%88%E6%83%85%E5%86%B5%EF%BC%9F.png)
execve() 的手册页说
execve() 执行文件名指向的程序。这会导致调用进程当前正在运行的程序被新程序替换,其中新初始化的堆栈、堆和(已初始化和未初始化的)数据段。
如果调用进程是由 vfork() 创建的,则意味着exec()为新程序提供了新的地址空间;它不会修改父地址空间。。
如果调用进程更一般地由 fork() 创建,那么旧的“堆栈、堆和(已初始化和未初始化的)数据段”通常会发生什么?他们的空间被释放了吗?
execve() 的行为是否取决于调用进程的创建方式?
在看到引用之前,我认为 execve() 会覆盖旧的“堆栈、堆和(初始化和未初始化的)数据段”,而不是创建新的。所以当我看到这句话时,想知道为什么要浪费新空间?
谢谢。
答案1
execve() 的行为是否取决于调用进程的创建方式?
不。
在看到引用之前,我认为 execve() 会覆盖旧的“堆栈、堆和(初始化和未初始化的)数据段”,而不是创建新的。
否:execve() 创建新段并释放旧段。
所以当我看到这句话时,想知道为什么要浪费新空间?
记住,我们正在谈论虚拟内存!
创建空白段仅分配少量物理内存,以跟踪该段。无论段有多大,该分配的大小都是固定的。
必须为写入的每个页分配一个物理页。父进程可能已写入大量页面。但是,如果子进程在运行时只使用了一点堆栈/堆/数据,那么它就没有充分的理由保留对父进程所有脏页的引用!如果父进程退出而子进程继续运行,则会浪费内存。
删除对旧段和旧页面的引用是最有效的方法。因为如果那是仅有的引用该内存,可以释放物理内存。