fork exec cow

当我点击一个可执行文件时,操作系统fork了一个子进程来执行这个可执行文件,对吗?
是的,当你点击一个可执行文件时,操作系统会创建一个子进程来执行这个可执行文件。具体来说,操作系统会通过以下步骤完成这个过程:

  1. 创建子进程(fork():操作系统会调用 fork() 系统调用来创建一个新的进程(子进程)。这个子进程是父进程(通常是一个 shell 或桌面环境)的一份拷贝,但不会执行父进程的代码。

  2. 执行新程序(exec():在子进程中,操作系统会调用 exec() 系统调用,将子进程的代码段替换为可执行文件的代码。此时,子进程开始执行新加载的程序。

这样,子进程执行的就是你点击的那个可执行文件,而父进程仍然保持运行状态。通过这种机制,操作系统能够并发地运行多个程序。


exec()负责将可执行文件从磁盘装载到内存中吗?

是的,exec() 系列系统调用(例如 execve())负责将可执行文件从磁盘加载到内存中,并将当前进程的内存空间替换为这个新加载的可执行文件的内容。

具体来说,exec() 会执行以下操作:

  1. 加载可执行文件exec() 将指定的可执行文件从磁盘加载到内存中。这包括加载文件的代码段、数据段以及其他必要的段(例如 BSS 段和堆栈段)。

  2. 替换进程内存exec() 替换当前进程的地址空间,使其内容变为新加载的可执行文件的内容。原有进程的代码、数据等都会被新的程序覆盖。

  3. 设置入口点exec() 设置新的程序入口点(通常是程序的 main 函数的地址),并将程序计数器(PC)设置为这个入口点,从而开始执行新程序的代码。

  4. 重新初始化堆栈exec() 重新初始化进程的堆栈,通常会传递命令行参数和环境变量给新程序。

一旦 exec() 成功调用,进程就会丢失其原来的代码和数据,完全变成了新的可执行文件的进程。然而,进程 ID (PID) 保持不变。


写时复制(cow)在这个过程中起什么作用?

写时复制(Copy-On-Write,COW)在 fork()exec() 过程中的作用主要体现在优化内存使用和提高性能。具体来说:

1. fork() 和 COW

当操作系统调用 fork() 时,会创建一个新的子进程,这个子进程最初是父进程的一个几乎完全的拷贝,包括父进程的地址空间(内存)。如果不使用 COW,操作系统将需要将整个父进程的内存空间逐字节地复制到子进程中,这会非常消耗时间和内存。

然而,大多数情况下,子进程在 fork() 后立即调用 exec() 来执行一个新的程序,这意味着子进程会放弃当前的内存空间,加载新的可执行文件。所以,在 fork() 之后,通常不会需要父进程的内存内容。

COW 优化了这个过程:

  • 共享内存:在 fork() 时,父进程和子进程不会立即复制整个内存空间,而是共享相同的物理内存页。只有在其中一个进程试图写入这些共享内存页时,才会触发真正的内存复制操作(即写时复制)。

  • 延迟复制:这样,如果子进程在 fork() 后立即执行 exec(),因为它还没有进行任何写操作,COW 机制可以避免不必要的内存复制,大大提高了性能。

2. exec() 和 COW

当子进程调用 exec() 时,整个进程的内存空间将被新的可执行文件替换,因此,COW 机制在 exec() 调用之后失去意义。在执行 exec() 时,操作系统将释放原来的共享内存页,并加载新的程序内容到内存中。

总结

  • fork():COW 允许父进程和子进程共享相同的内存页面,直到有一个进程进行写操作。这减少了不必要的内存复制,提高了性能。
  • exec():COW 提供的内存共享机制可以避免在调用 exec() 之前进行不必要的内存复制,但在 exec() 调用之后,这些共享内存将被新加载的可执行文件所取代。
(venv) C:\Users\Administrator\PycharmProjects\pythonProject>Python multiprocssing.py -d 2 -p www.baidu.com Traceback (most recent call last): File "<string>", line 1, in <module> File "C:\Program Files\Python36\lib\multiprocessing\spawn.py", line 105, in spawn_main exitcode = _main(fd) File "C:\Program Files\Python36\lib\multiprocessing\spawn.py", line 114, in _main prepare(preparation_data) File "C:\Program Files\Python36\lib\multiprocessing\spawn.py", line 225, in prepare _fixup_main_from_path(data['init_main_from_path']) File "C:\Program Files\Python36\lib\multiprocessing\spawn.py", line 277, in _fixup_main_from_path run_name="__mp_main__") File "C:\Program Files\Python36\lib\runpy.py", line 263, in run_path pkg_name=pkg_name, script_name=fname) File "C:\Program Files\Python36\lib\runpy.py", line 96, in _run_module_code mod_name, mod_spec, pkg_name, script_name) File "C:\Program Files\Python36\lib\runpy.py", line 85, in _run_code exec(code, run_globals) File "C:\Users\Administrator\PycharmProjects\pythonProject\multiprocssing.py", line 10, in <module> readed_path = multiprocessing.Manager().list() File "C:\Program Files\Python36\lib\multiprocessing\context.py", line 56, in Manager m.start() File "C:\Program Files\Python36\lib\multiprocessing\managers.py", line 513, in start self._process.start() File "C:\Program Files\Python36\lib\multiprocessing\process.py", line 105, in start self._popen = self._Popen(self) File "C:\Program Files\Python36\lib\multiprocessing\context.py", line 322, in _Popen return Popen(process_obj) File "C:\Program Files\Python36\lib\multiprocessing\popen_spawn_win32.py", line 33, in __init__ prep_data = spawn.get_preparation_data(process_obj._name) File "C:\Program Files\Python36\lib\multiprocessing\spawn.py", line 143, in get_preparation_data _check_not_importing_main() File "C:\Program Files\Python36\lib\multiprocessing\spawn.py", line 136, in _check_not_importing_main is not going to be frozen to produce an executable.''') RuntimeError: An attempt has been made to start a new process before the current process has finished its bootstrapping phase. This probably means that you are not using fork to start your child processes and you have forgotten to use the proper idiom in the main module: if __name__ == '__main__': freeze_support() ... The "freeze_support()" line can be omitted if the program is not going to be frozen to produce an executable.此错误的原因及解决方法
06-03
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值