Python 内置模块之 os 之 os.for()

官方文档:https://docs.python.org/zh-cn/3.8/library/argparse.html

简介

os.fork() 是 Python 中在 Unix/Linux 系统的一个函数,它在当前进程中创建一个子进程。这个函数是 os 模块的一部分,直接调用了 Unix/Linux 系统的 fork 系统调用。fork 系统调用非常基础且强大,允许操作系统创建一个新的进程,这个新进程是调用它的进程(父进程)的副本。

注意:

  • os.fork() 只在 Unix/Linux 系统上可用。如果你试图在 Windows 系统上使用它,会抛出一个 AttributeError 异常。
  • 创建进程(尤其是在循环中)时需要谨慎,以避免无意中产生大量的进程,导致所谓的 “fork 炸弹”

示例

在我们运行 Python 程序的时候,系统会创建一个新的 python 进程。如以下代码

1
2
3
import time 

time.sleep(20)

使用 fork 创建一个新的进程后,新进程是原进程的子进程,原进程为父进程。如果发生错误,则会抛出 OSError 异常。

1
2
3
4
5
6
7
8
9
10
11
# -*- coding: utf-8 -*-
import time

import os

try:
pid = os.fork()
except OSError, e:
pass

time.sleep(20)

运行代码,查看进程,在终端输出如下:

可以看出第二个 Python 进程就是第一个的子进程。

fork 进程后的程序流程

使用 fork 创建子进程后,子进程会复制父进程的数据信息,而后程序就分两个进程继续运行后面的程序,这也是 fork 名字的含义了。

  • 在子进程内,os.fork 会返回0;
  • 在父进程内,os.fork 会返回子进程的编号PID。

可以使用 PID 来区分两个进程:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
# -*- coding: utf-8 -*-
import time
import os

# 创建子进程前声明的变量
number = 7
try:
pid = os.fork()

if pid == 0:
print "this is child process"
number = number - 1
time.sleep(5)
print number
else:
print "this is parent process"
except OSError, e:
pass

上面代码中,在子进程创建前,声明了一个变量 number,然后在子进程中自减 1,最后打印出 number 的值,显然父进程打印出来的值为 7,子进程打印出来的值为 6。为了明显区分父进程和子进程,让子进程睡 3 秒,这样效果就比较明显了。

既然子进程是父进程创建的,那么父进程退出之后,子进程会被 PID 为 1 的进程接管,就是init进程了。这样子进程就不会受终端退出影响了,使用这个特性就可以创建在后台执行的程序,俗称守护进程(daemon)。

底层原理

在 Python 中,os.fork() 是通过底层的操作系统调用来实现的。具体地说,它使用了 POSIX 标准中的 fork() 系统调用。

fork() 系统调用会创建一个新的进程,新进程是原始进程的一个副本,包括代码、数据和资源等。在调用 os.fork() 时,操作系统会复制当前进程的所有信息,并将这个复制的进程作为新的子进程返回给父进程。

在底层,fork() 调用的过程如下:

  1. 操作系统为子进程创建一个新的进程控制块(Process Control Block)来存储子进程的状态信息。
  2. 操作系统复制父进程的代码段、数据段和堆栈等信息到子进程的地址空间。
  3. 子进程开始执行从 os.fork() 后的代码,而父进程继续执行原有的代码。
  4. 在子进程中,os.fork() 返回值为 0,使得子进程能够根据返回值判断自己是子进程。
  5. 在父进程中,os.fork() 返回值为子进程的进程ID,使得父进程能够根据返回值判断自己是父进程。

需要注意的是,fork() 调用会在父进程和子进程中创建一个完全相同的进程映像,包括进程的状态、文件描述符等。因此,在 fork() 后,父进程和子进程是相互独立的,各自有自己的内存空间和资源。

Reference


Python 内置模块之 os 之 os.for()
https://flepeng.github.io/021-Python-31-Python-标准库-Python-标准库之-os-之-os-fork/
作者
Lepeng
发布于
2021年3月17日
许可协议