父进程与子进程的关系,在不同操作系统下是不一样的,先讨论在 MacOS 或者 Linux 系统下,我们可以使用fork()
来探索父子进程的关系。
fork
可以生成一个与当前进程完全一样的子进程,如果当前进程是父进程,fork()返回的是进程的pid,如果是子进程则会返回0
import os
print('Process (%s) start...' % os.getpid())
# Only works on Unix/Linux/Mac:
pid = os.fork() # fork 时间点,父子进程完全一样
if pid == 0: # 子进程永远返回0
print('I am child process (%s) and my parent is %s.' % (os.getpid(), os.getppid()))
else: # 父进程返回子进程的ID
print('I (%s) just created a child process (%s).' % (os.getpid(), pid))
# Process (79869) start...
# I (79869) just created a child process (79870).
# I am child process (79870) and my parent is 79869.
fork
时完全一样子进程会得到所有父进程资源的副本,包括进程PCB中的内容(除了 pid ),也就是甚至连下一条执行的指令都是完全一样的,所以子进程是从 fork
继续执行,而不是从头执行。
因为 fork
时完全一样,所以并没有像想象中一样每个子进程也会不断生成3个子进程。因为 fork
出来的子进程是完全一样的,连 for
循环中的 i
值也是一样的。
import os
import time
print('Process (%s) start...' % os.getpid())
# Only works on Unix/Linux/Mac:
val = 0
print("I am root process ({})", os.getpid())
for i in range(3):
pid = os.fork()
if pid == 0:
print("created a process ({})".format(os.getpid()))
time.sleep(20) # 等会再退出,便于使用 pstree 观察
pstree -p 82258 # 查看父子进程关系
fork
后不共享内存父子进程不共享内存,fork()
之后两者再无瓜葛,当然子进程可以通过 getppid
找到父进程。
因为不共享内存,所以父进程中 val 值没有更改。
import os
import time
print('Process (%s) start...' % os.getpid())
# Only works on Unix/Linux/Mac:
val = 0
pid = os.fork() # fork 时间点,父子进程完全一样
if pid == 0: # 子进程永远返回0
while True:
val += 1
print('I am child process ({}). Value is {}'.format(os.getpid(), val))
time.sleep(1)
else: # 父进程返回子进程的ID
while True:
print('I am parent process ({}). Value is {}'.format(os.getpid(), val))
time.sleep(1)
父进程创建子进程和主程序调用子程序的不同?
不同OS中父子进程的执行策略不同,一般来说,父进程创建子进程后,父子进程并发执行,而主程序调用子程序后,主程序会停在调用语句,等待子程序返回,才会从调用语句的下一句开始执行。
在windows,如何实现fork()函数-CSDN社区
在Windows系统下没有一个函数可以实现UNIX下的fork()
函数,其原因是历史造成的,对于UNIX来说它一出生就是多用户的系统,所以它的所有进程都共有一个最原始的根进程(比如,上面 pstree 那张图中的 root 就是在 mac 下的根进程)。而windows生下来时是个单用户单任务系统(DOS),不存在这样的概念。
WIN32API函数CreateProcess用来创建一个新的进程和它的主线程,这个新进程运行指定的可执行文件。
在Windows下,如果想要模拟
fork()
,可以创建一个线程,把主线程中的公共变量如果硬要模似,CreateProcess()不如用CreateThread()更接近实际情况,把主thread中的所有公共变量都塞入一个结构/类的,带入新的thread中,这样可以大致完成"复制自身"的要求。但由于是thread,所以主thread死后,子thread不能独立存在,而fork()出来的子进程可以脱离主进程独立存在,这一点在window下只有CreateProcess()才略有相似之处。
在WINDOWS系统中,子进程是个什么样的概念啊?-CSDN社区
linux维护一个进程关系列表,而windows一般并不维护,换句话说windows的进程无法知道自己的子进程有哪些,父进程又是谁。windows下父子进程发生关系只在调用CreateProcess的那一瞬间。
linux创建子进程是父进程的拷贝,一般拥有父进程所能够访问的资源。windows创建子进程不是这样子,不特殊指定,子进程不能使用父进程的资源。