# 多进程
### fork()
Unix/Linux操作系统提供了一个`fork()`系统调用,它非常特殊。普通的函数调用,调用一次,返回一次,但是`fork()`调用一次,返回两次,因为操作系统自动把当前进程(称为父进程)复制了一份(称为子进程),然后,分别在父进程和子进程内返回。
子进程永远返回`0`,而父进程返回子进程的ID。这样做的理由是,一个父进程可以fork出很多子进程,所以,父进程要记下每个子进程的ID,而子进程只需要调用`getppid()`就可以拿到父进程的ID。
`os`模块封装了常见的系统调用,其中就包括`fork`,可以在Python程序中轻松创建子进程
```python
import os
print("Process (%s) start..."%os.getpid())
pid = os.fork()
if pid == 0:
print('I am child process (%s) and my parent is (%s).' % (os.getpid(), os.getppid()))
else:
print('I (%s) just created a child process (%s).' % (os.getpid(), pid))
```
### multiprocessing模块Process类
multiprocessing模块是跨平台版本的多进程模块。`multiprocessing`模块提供了一个`Process`类来代表一个进程对象。
```python
from multiprocessing import Process
import os
# 子进程要执行的代码
def run_proc(name):
print('Run child process %s (%s)...'%(name, os.getpid()))
if __name__ == '__main__':
print('Parent process %s.' % os.getpid())
p = Process(target=run_proc, args=('test', ))
print('Child process will start.')
p.start()
p.join()
print('Child process end.')
```
创建子进程时,只需要传入一个执行函数和函数的参数,创建一个`Process`实例,用`start()`方法启动,这样创建进程比`fork()`还要简单。
### multiprocessing模块Pool类
如果要启动大量的子进程,可以用进程池(Pool)的方式批量创建子进程。
```python
from multiprocessing import Pool
import os, time, random
def long_time_task(name):
print('Run task %s (%s)...' % (name, os.getpid()))
start = time.time()
time.sleep(random.random()*3)
end = time.time()
print('Task %s runs %0.2f seconds.' % (name, (end-start)))
if __name__ == '__main__':
print('Parent process %s.' % os.getpid())
p = Pool(4)
for i in range(5):
p.apply_async(long_time_task, args=(i, ))
print("Waithing for all subprocesses done...")
p.close()
p.join()
print('All subprocesses done.')
```
对`Pool`对象调用`join()`方法会等待所有子进程执行完毕,调用`join()`之前必须先调用`close()`,调用`close()`之后就不能继续添加新的`Process`了。
请注意输出的结果,task `0`,`1`,`2`,`3`是立刻执行的,而task `4`要等待前面某个task完成后才执行,这是因为`Pool`的默认大小在我的电脑上是4,因此,最多同时执行4个进程。这是`Pool`有意设计的限制,并不是操作系统的限制。
### 子进程
很多时候,子进程并不是自身,而是一个外部进程。我们创建了子进程后,还需要控制子进程的输入和输出。`subprocess`模块可以让我们非常方便地启动一个子进程,然后控制其输入和输出。
如果子进程还需要输入,则可以通过`communicate()`方法输入。
### 进程间通讯
进程间通信是通过`Queue`、`Pipes`等实现的。