有人能给我解释一下这个os.fork()示例吗?

10 投票
2 回答
13225 浏览
提问于 2025-04-18 08:40

[代码摘自《Programming Python》第四版,作者:Mark Lutz]

"forks child processes until you type 'q'"
import os
def child():
    print('Hello from child', os.getpid())
    os._exit(0) # else goes back to parent loop

def parent():
    while True:
        newpid = os.fork()
        if newpid == 0:
            child()
        else:
            print('Hello from parent', os.getpid(), newpid)
        if input() == 'q': break

parent()

运行这段代码时的输出结果:

Hello from parent 2057 2062 
Hello from child 2062

Hello from parent 2057 2068 
Hello from child 2068

Hello from parent 2057 2069 
Hello from child 2069

Hello from parent 2057 2070 
Hello from child 2070 
q

我理解的内容:

  1. os.fork() 是用来启动一个与当前进程并行的新进程。
  2. os.fork() 会复制当前的 Python 会话,并在并行中打开这个复制的会话。
  3. os.fork() 会返回新进程的 ID。

我不理解的内容:

  1. 为什么在代码运行时,os.getpid() 的值从来没有改变?
  2. 为什么会调用 child() 这个函数?假设 newpid 不等于 0,那么程序会打印出 print('Hello from parent', os.getpid(), newpid)。但是之后,它却打印了子进程的内容,而不是像 if 语句后那样要求输入。
  3. os._exit(0) 是干什么的?

非常感谢你的时间。:)

2 个回答

3
  1. 因为只要你的父进程在运行,它的进程ID(pid)就一直是一样的(就像在不停地循环:while True:)。
  2. 子进程其实是父进程的一个复制品。这就是os.fork的作用!这个函数会返回子进程的进程ID给父进程。所以父进程会执行if else语句的第二部分,而所有的子进程则执行第一部分,因为对于子进程来说,os.fork会返回0。
  3. os._exit其实是os.exit()的简化版,专门用来给子进程使用的。
7

1: 为什么运行代码时 os.getpid() 的值从来没有改变?

os.getpid() 的值对于父进程来说是不会改变的,因为它始终是同一个进程。而对于子进程来说,每次调用 fork() 都会创建一个全新的子进程,这个子进程会有自己的进程ID(PID),所以它的值会变化。

2: 为什么会调用 child() 函数?假设 newpid 的值不等于0,那么程序会打印出 print('Hello from parent', os.getpid(), newpid)。但是之后,它却打印了子进程的内容,而不是像if语句后那样请求输入。

子进程会被调用是因为现在有两个进程在运行。一个是调用了 child() 函数,另一个是调用了 print 函数。它们在争抢打印到屏幕的机会,这种情况下你看到的是父进程先打印了“胜利”。

3: os._exit(0) 是干什么的?

请看这里:https://docs.python.org/2/library/os.html#os._exit

它会直接退出进程,状态码为n,而不会调用清理处理程序,也不会刷新标准输入输出缓冲区等。

撰写回答