# è¿ç¨
**è¿ç¨ï¼processï¼æ¯æ£å¨è¿è¡çç¨åºçå®ä¾ï¼ä½ä¸ä¸ªç¨åºå¯è½ä¼äº§çå¤ä¸ªè¿ç¨**ãæ¯å¦ï¼æå¼ Chrome æµè§å¨ç¨åºï¼å®å¯è½ä¼äº§çå¤ä¸ªè¿ç¨ï¼ä¸»ç¨åºéè¦ä¸ä¸ªè¿ç¨ï¼ä¸ä¸ªç½é¡µæ ç¾éè¦ä¸ä¸ªè¿ç¨ï¼ä¸ä¸ªæä»¶ä¹éè¦ä¸ä¸ªè¿ç¨ï¼ççã
æ¯ä¸ªè¿ç¨é½æèªå·±çå°å空é´ï¼å
åï¼æ°æ®æ 以åå
¶ä»è®°å½å
¶è¿è¡ç¶æçè¾
婿°æ®ï¼ä¸åçè¿ç¨åªè½ä½¿ç¨æ¶æ¯éåãå
±äº«å
åçè¿ç¨é´é讯ï¼IPCï¼æ¹æ³è¿è¡éä¿¡ï¼èä¸è½ç´æ¥å
±äº«ä¿¡æ¯ã
# fork()
å¨ä»ç» Python çè¿ç¨ç¼ç¨ä¹åï¼è®©æä»¬å
çç Unix/Linux ä¸ç `fork` 彿°ãå¨ Unix/Linux ç³»ç»ä¸ï¼`fork` 彿°è¢«ç¨äºå建è¿ç¨ãè¿ä¸ªå½æ°å¾ç¹æ®ï¼å¯¹äºæ®éç彿°ï¼è°ç¨å®ä¸æ¬¡ï¼è¿å䏿¬¡ï¼ä½æ¯è°ç¨ `fork` 䏿¬¡ï¼å®è¿å两次ãäºå®ä¸ï¼`fork` 彿°åå»ºäºæ°çè¿ç¨ï¼æä»¬æå®ç§°ä¸ºåè¿ç¨ï¼åè¿ç¨å 乿¯å½åè¿ç¨ï¼å³ç¶è¿ç¨ï¼çä¸ä¸ªæ·è´ï¼å®ä¼å¤å¶ç¶è¿ç¨çä»£ç æ®µï¼å æ æ®µåæ°æ®æ®µã
对äºç¶è¿ç¨ï¼`fork` 彿°è¿åäºåè¿ç¨çè¿ç¨å· pidï¼å¯¹äºåè¿ç¨ï¼`fork` 彿°åè¿å `0`ï¼è¿ä¹æ¯ `fork` 彿°è¿å两次çåå ï¼æ ¹æ®è¿åå¼ï¼æä»¬å¯ä»¥å¤æè¿ç¨æ¯ç¶è¿ç¨è¿æ¯åè¿ç¨ã
ä¸é¢æä»¬ç䏿®µ C 代ç ï¼å®å±ç¤ºäº fork çåºæ¬ä½¿ç¨ï¼
```c
#include
#include
int main(int argc, char const *argv[])
{
int pid;
pid = fork(); // ä½¿ç¨ fork 彿°
if (pid < 0) {
printf("Fail to create process\n");
}
else if (pid == 0) {
printf("I am child process (%d) and my parent is (%d)\n", getpid(), getppid());
}
else {
printf("I (%d) just created a child process (%d)\n", getpid(), pid);
}
return 0;
}
```
å
¶ä¸ï¼`getpid` ç¨äºè·åå½åè¿ç¨å·ï¼`getppid` ç¨äºè·åç¶è¿ç¨å·ã
äºå®ä¸ï¼Python ç os 模åå
å«äºæ®éçæä½ç³»ç»åè½ï¼è¯¥æ¨¡å乿ä¾äº `fork` 彿°ï¼æä¸é¢çä»£ç æ¹æç¨ Python æ¥å®ç°ï¼å¦ä¸ï¼
```python
import os
pid = os.fork()
if pid < 0:
print 'Fail to create process'
elif 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)
```
è¿è¡ä¸é¢ç代ç ï¼äº§çå¦ä¸è¾åºï¼
```
I (86645) just created a child process (86646).
I am child process (86646) and my parent is (86645).
```
éè¦æ³¨æçæ¯ï¼è½ç¶åè¿ç¨å¤å¶äºç¶è¿ç¨çä»£ç æ®µåæ°æ®æ®µçï¼ä½æ¯ä¸æ¦åè¿ç¨å¼å§è¿è¡ï¼åè¿ç¨åç¶è¿ç¨å°±æ¯ç¸äºç¬ç«çï¼å®ä»¬ä¹é´ä¸åå
±äº«ä»»ä½æ°æ®ã
# å¤è¿ç¨
Python æä¾äºä¸ä¸ª [multiprocessing][mp] 模åï¼å©ç¨å®ï¼æä»¬å¯ä»¥æ¥ç¼å跨平å°çå¤è¿ç¨ç¨åºï¼ä½éè¦æ³¨æçæ¯ multiprocessing å¨ Windows å Linux å¹³å°çä¸ä¸è´æ§ï¼ä¸æ ·ç代ç å¨ Windows å Linux ä¸è¿è¡çç»æå¯è½ä¸åãå 为 Windows çè¿ç¨æ¨¡åå Linux ä¸ä¸æ ·ï¼Windows 䏿²¡æ forkã
æä»¬å
æ¥çä¸ä¸ªç®åçä¾åï¼è¯¥ä¾åæ¼ç¤ºäºå¨ä¸»è¿ç¨ä¸å¯å¨ä¸ä¸ªåè¿ç¨ï¼å¹¶çå¾
å
¶ç»æï¼ä»£ç å¦ä¸ï¼
```python
import os
from multiprocessing import Process
# åè¿ç¨è¦æ§è¡ç代ç
def child_proc(name):
print 'Run child process %s (%s)...' % (name, os.getpid())
if __name__ == '__main__':
print 'Parent process %s.' % os.getpid()
p = Process(target=child_proc, args=('test',))
print 'Process will start.'
p.start()
p.join()
print 'Process end.'
```
å¨ä¸é¢ç代ç ä¸ï¼æä»¬ä» multiprocessing 模åå¼å
¥äº Processï¼Process æ¯ä¸ä¸ªç¨äºå建è¿ç¨å¯¹è±¡çç±»ï¼å
¶ä¸ï¼target æå®äºè¿ç¨è¦æ§è¡ç彿°ï¼args æå®äºåæ°ãå¨å建äºè¿ç¨å®ä¾ p ä¹åï¼æä»¬è°ç¨ start æ¹æ³å¼å§æ§è¡è¯¥åè¿ç¨ï¼æ¥çï¼æä»¬åè°ç¨äº join æ¹æ³ï¼è¯¥æ¹æ³ç¨äºé»å¡åè¿ç¨ä»¥å¤çææè¿ç¨ï¼è¿éæç¶è¿ç¨ï¼ï¼å½åè¿ç¨æ§è¡å®æ¯åï¼ç¶è¿ç¨æä¼ç»§ç»æ§è¡ï¼å®é常ç¨äºè¿ç¨é´ç忥ã
å¯ä»¥çå°ï¼ç¨ä¸é¢è¿ç§æ¹å¼æ¥å建è¿ç¨æ¯ç´æ¥ä½¿ç¨ `fork` æ´ç®åææãç°å¨ï¼è®©æä»¬çä¸è¾åºç»æï¼
```
Parent process 7170.
Process will start.
Run child process test (10075)...
Process end.
```
## multiprocessing ä¸å¹³å°æå
³
``` python
import random
import os
from multiprocessing import Process
num = random.randint(0, 100)
def show_num():
print("pid:{}, num is {}".format(os.getpid(), num))
if __name__ == "__main__":
print("pid:{}, num is {}".format(os.getpid(), num))
p = Process(target=show_num)
p.start()
p.join()
```
å¨ Windows ä¸è¿è¡ä»¥ä¸ä»£ç ï¼è¾åºçç»æå¦ä¸ï¼ä½ å¾å°ä¸ä¸æ ·çç»æä¹æ¯å¯¹çï¼ï¼
```
pid:6504, num is 25
pid:6880, num is 6
```
æä»¬åç°ï¼num ç弿¯ä¸ä¸æ ·çï¼
å¨ Linux ä¸è¿è¡ä»¥ä¸ä»£ç ï¼å¯ä»¥çå° num ç弿¯ä¸æ ·çï¼
```
pid:11747, num is 13
pid:11748, num is 13
```
è¿æ¯å ä¸ºæ ¹æ®ä¸åçå¹³å°ï¼multiprocessingæ¯æä¸ç§å¯å¨è¿ç¨çåæ³ï¼
#### spawn
ç¶è¿ç¨ä¼å¯å¨ä¸ä¸ªæ°çè§£éå¨ï¼åè¿ç¨åªä¼ç»§æ¿run()æéçèµæºã
ä¸å¿
è¦çæä»¶æè¿°ç¬¦å奿ï¼ä¸ç§æéï¼ä¸ä¼è¢«ç»§æ¿ã
è¯¥æ¹æ³åforkï¼forkserverç¸æ¯ï¼å¯å¨è¿ç¨è¾æ
¢ã
å¯å¨UnixåWindowsä¸ä½¿ç¨ã Windowsä¸çé»è®¤è®¾ç½®ã
#### fork
ç¶è¿ç¨ä½¿ç¨ os.fork() æ¥äº§ç Python è§£éå¨ååã
åè¿ç¨å¨å¼å§æ¶å®é
ä¸ä¸ç¶è¿ç¨ç¸åï¼å¹¶ä¸ä¼ç»§æ¿ç¶è¿ç¨çææèµæºã
å¤çº¿ç¨çå®å
¨æ¯æé®é¢çã
åªè½å¨Unixä¸ä½¿ç¨ãUnixä¸çé»è®¤è®¾ç½®ã
#### forkserver
ç¨åºå¯å¨å¹¶éæ©forkserverå¯å¨æ¹æ³æ¶ï¼å°å¯å¨ä¸ä¸ªæå¡å¨è¿ç¨ã
ä¹åæ¯å½éè¦ä¸ä¸ªæ°è¿ç¨æ¶ï¼ç¶è¿ç¨å°±ä¼è¿æ¥å°æå¡å¨å¹¶è¯·æ±å®ååä¸ä¸ªæ°è¿ç¨ã
ååæå¡å¨è¿ç¨æ¯å线ç¨çï¼å æ¤ä½¿ç¨ os.fork() æ¯å®å
¨çã
没æä¸å¿
è¦çèµæºè¢«ç»§æ¿ã
å¯å¨Unixå¹³å°ä¸ä½¿ç¨ï¼å¹¶æ¯æéè¿Unix管éä¼ éæä»¶æè¿°ç¬¦ã
## 使ç¨è¿ç¨æ± å建å¤ä¸ªè¿ç¨
å¨ä¸é¢ï¼æä»¬åªæ¯å建äºä¸ä¸ªè¿ç¨ï¼å¦æè¦å建å¤ä¸ªè¿ç¨å¢ï¼Python æä¾äº**è¿ç¨æ± **çæ¹å¼ï¼è®©æä»¬æ¹éå建åè¿ç¨ï¼è®©æä»¬çä¸ä¸ªç®åç示ä¾ï¼
```python
import os, time
from multiprocessing import Pool
def foo(x):
print 'Run task %s (pid:%s)...' % (x, os.getpid())
time.sleep(2)
print 'Task %s result is: %s' % (x, x * x)
if __name__ == '__main__':
print 'Parent process %s.' % os.getpid()
p = Pool(4) # 设置è¿ç¨æ°
for i in range(5):
p.apply_async(foo, args=(i,)) # 设置æ¯ä¸ªè¿ç¨è¦æ§è¡ç彿°ååæ°
print 'Waiting for all subprocesses done...'
p.close()
p.join()
print 'All subprocesses done.'
```
å¨ä¸é¢ç代ç ä¸ï¼Pool ç¨äºçæè¿ç¨æ± ï¼å¯¹ Pool 对象è°ç¨ apply_async æ¹æ³å¯ä»¥ä½¿æ¯ä¸ªè¿ç¨å¼æ¥æ§è¡ä»»å¡ï¼ä¹å°±è¯´ä¸ç¨çä¸ä¸ä¸ªä»»å¡æ§è¡å®ææ§è¡ä¸ä¸ä¸ªä»»å¡ï¼close æ¹æ³ç¨äºå
³éè¿ç¨æ± ï¼ç¡®ä¿æ²¡ææ°çè¿ç¨å å
¥ï¼join æ¹æ³ä¼çå¾
ææåè¿ç¨æ§è¡å®æ¯ã
ççæ§è¡ç»æï¼
```python
Parent process 7170.
Run task 1 (pid:10320)...
Run task 0 (pid:10319)...
Run task 3 (pid:10322)...
Run task 2 (pid:10321)...
Waiting for all subprocesses done...
Task 1 result is: 1
Task 0 result is: 0
Run task 4 (pid:10320)...
Task 3 result is: 9
Task 2 result is: 4
Task 4 result is: 16
All subprocesses done.
```
# è¿ç¨é´éä¿¡
è¿ç¨é´çéä¿¡å¯ä»¥éè¿ç®¡éï¼Pipeï¼ï¼éåï¼Queueï¼çå¤ç§æ¹å¼æ¥å®ç°ãPython ç multiprocessing 模åå°è£
äºåºå±çå®ç°æºå¶ï¼è®©æä»¬å¯ä»¥å¾å®¹æå°å®ç°è¿ç¨é´çéä¿¡ã
ä¸é¢ä»¥éåï¼Queueï¼ä¸ºä¾ï¼å¨ç¶è¿ç¨ä¸å建两个åè¿ç¨ï¼ä¸ä¸ªå¾éååæ°æ®ï¼ä¸ä¸ªä»å¯¹åè¯»æ°æ®ï¼ä»£ç å¦ä¸ï¼
```python
# -*- coding: utf-8 -*-
from multiprocessing import Process, Queue
# åéåä¸åå
¥æ°æ®
def write_task(q):
try:
n = 1
while n < 5:
print "write, %d" % n
q.put(n)
time.sleep(1)
n += 1
except BaseException:
print "write_task error"
finally:
print "write_task end"
# ä»éåè¯»åæ°æ®
def read_task(q):
try:
n = 1
while n < 5:
print "read, %d" % q.get()
time.sleep(1)
n += 1
except BaseException:
print "read_task error"
finally:
print "read_task end"
if __name__ == "__main__":
q = Queue() # ç¶è¿ç¨å建Queueï¼å¹¶ä¼ ç»å个åè¿ç¨
pw = Process(target=write_task, args=(q,))
pr = Process(target=read_task, args=(q,))
pw.start() # å¯å¨åè¿ç¨ pwï¼åå
¥
pr.start() # å¯å¨åè¿ç¨ prï¼è¯»å
pw.join() # çå¾
pw ç»æ
pr.join() # çå¾
pr ç»æ
print "DONE"
```
æ§è¡ç»æå¦ä¸ï¼
```python
write, 1
read, 1
write, 2
read, 2
write, 3
read, 3
write, 4
read, 4
write_task end
read_task end
DONE
```
# å°ç»
- è¿ç¨æ¯æ£å¨è¿è¡çç¨åºçå®ä¾ã
- ç±äºæ¯ä¸ªè¿ç¨é½æåèªçå
å空é´ï¼æ°æ®æ çï¼æä»¥åªè½ä½¿ç¨è¿ç¨é´é讯ï¼Inter-Process Communication, IPCï¼ï¼èä¸è½ç´æ¥å
±äº«ä¿¡æ¯ã
- Python ç multiprocessing 模åå°è£
äºåºå±çå®ç°æºå¶ï¼è®©æä»¬å¯ä»¥æ´ç®åå°ç¼åå¤è¿ç¨ç¨åºã
# åèèµæ
- [å¤è¿ç¨ - å»éªå³°ç宿¹ç½ç«](http://www.liaoxuefeng.com/wiki/001374738125095c955c1e6d8bb493182103fac9270762a000/0013868323401155ceb3db1e2044f80b974b469eb06cb43000)
- [Linuxä¸Forkä¸Execä½¿ç¨ - hicjiajia - å客å](http://www.cnblogs.com/hicjiajia/archive/2011/01/20/1940154.html)
- [Python ä¸çè¿ç¨ã线ç¨ãåç¨ã忥ã弿¥ãåè° - ä¸çäºåå¨ - SegmentFault](https://segmentfault.com/a/1190000001813992)
- [ç¼ç¨ä¸çè¿ç¨ã线ç¨ãåç¨ã忥ã弿¥ãåè° Â· æµ®ç忥é²](https://wangdashuaihenshuai.github.io/2015/10/17/%E7%BC%96%E7%A8%8B%E4%B8%AD%E7%9A%84%E8%BF%9B%E7%A8%8B%E3%80%81%E7%BA%BF%E7%A8%8B%E3%80%81%E5%8D%8F%E7%A8%8B%E3%80%81%E5%90%8C%E6%AD%A5%E3%80%81%E5%BC%82%E6%AD%A5%E3%80%81%E5%9B%9E%E8%B0%83/)
- [pythonä¸å¤è¿ç¨ä»¥åå¤çº¿ç¨ç¼ç¨çæ»ç» - Codefly](http://sunms.codefly.top/2016/11/05/python%E4%B8%AD%E5%A4%9A%E8%BF%9B%E7%A8%8B%E4%BB%A5%E5%8F%8A%E5%A4%9A%E7%BA%BF%E7%A8%8B%E7%BC%96%E7%A8%8B%E7%9A%84%E6%80%BB%E7%BB%93/)
- [multithreading - Python multiprocessing.Pool: when to use apply, apply_async or map? - Stack Overflow](http://stackoverflow.com/questions/8533318/python-multiprocessing-pool-when-to-use-apply-apply-async-or-map)
- [multiprocessing --- åºäºè¿ç¨çå¹¶è¡Â¶](https://docs.python.org/zh-cn/3/library/multiprocessing.html)
[mp]: https://docs.python.org/2/library/multiprocessing.html