章节号 | 内容 |
---|---|
1图片格式(png) | 宽度大于620px,保持高宽比减低为620px |
1-1 | 应用 |
1-1-1 | 方法 |
第1章节 多任务概念理解
第2章节 fork创建子进程
-
1-1 fork创建子进程—简单测试
In [1]:
...: import os
...: import time
...: ret = os.fork()
...:
...: if ret == 0:
...: while True:
...: print("==1==")
...: time.sleep(1)
...: else:
...: while True:
...: print("==2==")
...: time.sleep(1)
...:
==2==
==1==
==2==
==1==
==2==
==1==
==2==
==1==
==2==
==1==
.
.
.
↑用vscdoe调试出错。
程序走到ret = os.fork()
,将创建一个新进程
程序走到ret = os.fork()
这行代码,先算的是右边,计算右边的时候,程序开始一分为二。
os.fork()
会返回2个特殊值,一个大于0,表示父进程,一个等于0,为子进程。
In [2]: import os
...: import time
...: ret = os.fork()
...:
...: if ret == 0:
...: while True:
...: print("==1==")
...: print(ret)
...: time.sleep(1)
...: else:
...: while True:
...: print("==2==")
...: print(ret)
...: time.sleep(1)
...:
==2==
8537
==1==
0
==2==
8537
==1==
0
.
.
.
↑涉及多进程,fork()的返回值不一定。父子谁先执行也不一定。你只能确定父执行什么代码,子执行什么代码。
-
1-2 fork创建子进程—getpid、getppid
In [3]:
...: import os
...: import time
...: ret = os.fork()
...:
...: if ret == 0:
...: while True:
...: print("==1==,pid=%d,ppid=%d"%(os.getpid(),os.getppid()))
...: print(ret)
...: time.sleep(1)
...: else:
...: while True:
...: print("==2==,pid=%d"%os.getpid())
...: print(ret)
...: time.sleep(1)
...:
==2==,pid=9464
9525
==1==,pid=9525,ppid=9464
0
.
.
.
In [4]: ?os.getpid()
Signature: os.getpid()
Docstring: Return the current process id.
Type: builtin_function_or_method
In [5]: ?os.getppid()
Signature: os.getppid()
Docstring:
Return the parent's process id.
If the parent process has already exited, Windows machines will still
return its id; others systems will return the id of the 'init' process (1).
Type: builtin_function_or_method
↑os.fork()
返回给父进程的大于0的值,就是子进程的PID。
-
1-3 fork创建子进程—父子的先后顺序
使用终端调试下列代码:
vim 1.py
1 import os
2 import time
3 ret = os.fork()
4 if ret==0:
5 print("subprocess")
6 time.sleep(1)
7 print("subprocess over")
8 else:
9 print("parent process")
10
python3 1.py
li@li-ThinkPad-T420s:~$ python3 1.py
parent process
subprocess
li@li-ThinkPad-T420s:~$ subprocess over
↑多进程结构中,只要主进程结束,就会出现命令提示符,就可以进行下一次操作。但是此时子进程还没有结束,所以命令行提示符出现后,子进程还会执行输出,就输出到了命令提示符后面了。同时因为默认print()有换行,此时光标会被挤到下一行。
↑结论:如果主进程结束了,就直接退出了,不会等子进程结束。
1 import os
2 import time
3 ret = os.fork()
4 if ret==0:
5 print("subprocess")
6 time.sleep(1)
7 print("subprocess over")
8 else:
9 print("parent process")
10
11 print("over")
li@li-ThinkPad-T420s:~$ python3 1.py
parent process
over
subprocess
li@li-ThinkPad-T420s:~$ subprocess over
over
↑“over”会被执行2次,父子各一次。
注意点:一个进程的系统开销很大。
-
1-4 fork创建子进程—全局变量在多进程中不共享
1
2 import os
3 import time
4 ret = os.fork()
5 if ret==0:
6 while True:
7 print("subprocess")
8 print("subprocess")
9 print("subprocess")
10 time.sleep(1)
11 else:
12 while True:
13 print("parent process")
14 time.sleep(1)
li@li-ThinkPad-T420s:~$ python3 3.py
parent process
subprocess
subprocess
subprocess
parent process
subprocess
subprocess
subprocess
parent process
subprocess
subprocess
subprocess
subprocess
parent process
subprocess
subprocess
parent process
subprocess
subprocess
subprocess
subprocess
subprocess
subprocess
.
.
.
↑父子进程执行的不确定性的单位
,是可大可小的,不一定三句print("subprocess")
都执行完了才会切换到print("parent process")
。
1 import os
2 import time
3
4 g_n=100
5
6 ret = os.fork()
7 if ret==0:
8 print("subprocess")
9 g_n+=1
10 print("sub.n=%d"%g_n)
11 else:
12 time.sleep(3)
13 print("parent process")
14 print("par.n=%d"%g_n)
subprocess
sub.n=101
parent process
par.n=100
↑创建了子进程之后,代码共享,但是数据(全局、局部)是独享,个人有一份,互不干扰。
缺点:进程间数据不共享。如何解决?进程间通信
。
-
1-5 fork创建子进程—多个fork
1 import os
2 import time
3 ret = os.fork()
4 if ret == 0:
5 print("fork1.subprocess")
6
7 else:
8
9 print("fork1.parent process")
10
11 ret = os.fork()
12 if ret == 0:
13 print("fork2.subprocess")
14
15 else:
16
17 print("fork2.parent process")
18
19
20 ret = os.fork()
21 if ret == 0:
22 print("fork3.subprocess")
23
24 else:
25
26 print("fork3.subprocess")
li@li-ThinkPad-T420s:~$ python3 5.py
fork1.parent process
fork1.subprocess
fork2.parent process
fork2.parent process
fork2.subprocess
fork3.subprocess
fork3.subprocess
fork3.subprocess
fork3.subprocess
fork3.subprocess
fork2.subprocess
fork3.subprocess
li@li-ThinkPad-T420s:~$ fork3.subprocess
fork3.subprocess
一次fork(),1变2
二次fork(),2变4
三次fork(),4变8
2+4+8=14
如果你把第二个fork()放在某一个进程中,则本次fork只能增加一个进程。
如果你把第二个fork()放在全局,则第一个fork()产生的2个进程,各自会再产生一个进程,总进程将变为4。
1 import os
2 import time
3 print("before,%d"%os.getpid())
4 ret = os.fork()
5 if ret == 0:
6 print("fork1.subprocess,%d"%os.getpid())
7
8 else:
9
10 print("fork1.parent process,%d"%os.getpid())
11
12 ret = os.fork()
13 if ret == 0:
14 print("fork2.subprocess,%d"%os.getpid())
15
16 else:
17
18 print("fork2.parent process,%d"%os.getpid())
li@li-ThinkPad-T420s:~$ python3 6.py
before,15844
fork1.parent process,15844
fork1.subprocess,15845
fork2.parent process,15844
fork2.subprocess,15846
↑把第二个fork()放在父进程中,一共产生3个进程。
↓思考下例:
1 import os
2
#1变2
3 os.fork()
#2变4
4 os.fork()
#4变8
5 os.fork()
6
7 print("------1------")
------1------
------1------
------1------
------1------
li@li-ThinkPad-T420s:~$ ------1------
------1------
------1------
------1------
↑每调用一次,进程数乘以2
↓危险危险危险危险危险危险危险
import os
os.fork()
os.fork()
while True:
os.fork()
print("------1------")
↑fork炸弹。