赞
踩
当我点击一个可执行文件时,操作系统fork了一个子进程来执行这个可执行文件,对吗?
是的,当你点击一个可执行文件时,操作系统会创建一个子进程来执行这个可执行文件。具体来说,操作系统会通过以下步骤完成这个过程:
创建子进程(fork()
):操作系统会调用 fork()
系统调用来创建一个新的进程(子进程)。这个子进程是父进程(通常是一个 shell 或桌面环境)的一份拷贝,但不会执行父进程的代码。
执行新程序(exec()
):在子进程中,操作系统会调用 exec()
系统调用,将子进程的代码段替换为可执行文件的代码。此时,子进程开始执行新加载的程序。
这样,子进程执行的就是你点击的那个可执行文件,而父进程仍然保持运行状态。通过这种机制,操作系统能够并发地运行多个程序。
exec()负责将可执行文件从磁盘装载到内存中吗?
是的,exec()
系列系统调用(例如 execve()
)负责将可执行文件从磁盘加载到内存中,并将当前进程的内存空间替换为这个新加载的可执行文件的内容。
具体来说,exec()
会执行以下操作:
加载可执行文件:exec()
将指定的可执行文件从磁盘加载到内存中。这包括加载文件的代码段、数据段以及其他必要的段(例如 BSS 段和堆栈段)。
替换进程内存:exec()
替换当前进程的地址空间,使其内容变为新加载的可执行文件的内容。原有进程的代码、数据等都会被新的程序覆盖。
设置入口点:exec()
设置新的程序入口点(通常是程序的 main
函数的地址),并将程序计数器(PC)设置为这个入口点,从而开始执行新程序的代码。
重新初始化堆栈:exec()
重新初始化进程的堆栈,通常会传递命令行参数和环境变量给新程序。
一旦 exec()
成功调用,进程就会丢失其原来的代码和数据,完全变成了新的可执行文件的进程。然而,进程 ID (PID) 保持不变。
写时复制(cow)在这个过程中起什么作用?
写时复制(Copy-On-Write,COW)在 fork()
和 exec()
过程中的作用主要体现在优化内存使用和提高性能。具体来说:
fork()
和 COW当操作系统调用 fork()
时,会创建一个新的子进程,这个子进程最初是父进程的一个几乎完全的拷贝,包括父进程的地址空间(内存)。如果不使用 COW,操作系统将需要将整个父进程的内存空间逐字节地复制到子进程中,这会非常消耗时间和内存。
然而,大多数情况下,子进程在 fork()
后立即调用 exec()
来执行一个新的程序,这意味着子进程会放弃当前的内存空间,加载新的可执行文件。所以,在 fork()
之后,通常不会需要父进程的内存内容。
COW 优化了这个过程:
共享内存:在 fork()
时,父进程和子进程不会立即复制整个内存空间,而是共享相同的物理内存页。只有在其中一个进程试图写入这些共享内存页时,才会触发真正的内存复制操作(即写时复制)。
延迟复制:这样,如果子进程在 fork()
后立即执行 exec()
,因为它还没有进行任何写操作,COW 机制可以避免不必要的内存复制,大大提高了性能。
exec()
和 COW当子进程调用 exec()
时,整个进程的内存空间将被新的可执行文件替换,因此,COW 机制在 exec()
调用之后失去意义。在执行 exec()
时,操作系统将释放原来的共享内存页,并加载新的程序内容到内存中。
fork()
时:COW 允许父进程和子进程共享相同的内存页面,直到有一个进程进行写操作。这减少了不必要的内存复制,提高了性能。exec()
时:COW 提供的内存共享机制可以避免在调用 exec()
之前进行不必要的内存复制,但在 exec()
调用之后,这些共享内存将被新加载的可执行文件所取代。Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。