Python并发编程—fork的使用

基于fork的多进程编程

fork使用

pid = os.fork()
功能: 创建新的进程
返回值:整数,如果创建进程失败返回一个负数,如果成功则在原有进程中返回新进程的PID,在新进程中返回0

注意:

  • 子进程会复制父进程全部内存空间,从fork下一句开始执行。
  • 父子进程各自独立运行,运行顺序不一定。
  • 利用父子进程fork返回值的区别,配合if结构让父子进程执行不同的内容几乎是固定搭配。
  • 父子进程有各自特有特征比如PID PCB 命令集等。
  • 父进程fork之前开辟的空间子进程同样拥有,父子进程对各自空间的操作不会相互影响。
 1 import os
 2 from time import sleep
 3 
 4 pid = os.fork()
 5 
 6 if pid < 0:
 7   print("Create process failed")
 8 elif pid == 0:
 9   os._exit(0)
10   sleep(3)
11   print("New process")
12 else:
13   sleep(5)
14   print("Old process")
15 
16 print("Fork test end")
基于fork的进程创建演示1
 1 import os
 2 from time import sleep
 3 
 4 print("=========================")
 5 a = 1
 6 
 7 pid = os.fork()
 8 
 9 if pid < 0:
10   print("Create process failed")
11 elif pid == 0:
12   print("New process")
13   print("a = ",a)
14   a = 10000
15 else:
16   sleep(1)
17   print("Old process")
18   print("a:",a)
19 
20 print("All a = ",a)
基于fork的进程创建演示2

进程相关函数

os.getpid()

  • 功能: 获取一个进程的PID值
  • 返回值: 返回当前进程的PID

os.getppid()

  • 功能: 获取父进程的PID号
  • 返回值: 返回父进程PID
 1 # 获取pid值
 2 
 3 import os
 4 import time
 5 
 6 pid = os.fork()
 7 
 8 if pid < 0:
 9   print("Error")
10 elif pid == 0:
11   time.sleep(1)
12   print("Child PID:",os.getpid())
13   print("Get parent PID:",os.getppid())
14 else:
15   print("Get child PID:",pid)
16   print("Parent PID:",os.getpid())
get_pid

os._exit(status)

  • 功能: 结束一个进程
  • 参数:进程的终止状态

sys.exit([status])

  • 功能:退出进程
  • 参数:整数 表示退出状态
  • 字符串 表示退出时打印内容
1 import os
2 import sys
3 
4 # os._exit(1)
5 sys.exit("退出进程")
6 
7 print("Process exit")
exit

孤儿和僵尸

1.孤儿进程 : 父进程先于子进程退出,此时子进程成为孤儿进程。

特点: 孤儿进程会被系统进程收养,此时系统进程就会成为孤儿进程新的父进程,孤儿进程退出该进程会自动处理。

2.僵尸进程 : 子进程先于父进程退出,父进程又没有处理子进程的退出状态,此时子进程就会称为僵尸进程。

特点: 僵尸进程虽然结束,但是会存留部分PCB在内存中,大量的僵尸进程会浪费系统的内存资源。

3.如何避免僵尸进程产生

1)使用wait函数处理子进程退出

```		
pid,status = os.wait()
功能:在父进程中阻塞等待处理子进程退出
返回值: pid 退出的子进程的PID     status 子进程退出状态 ```
 1 import os
 2 
 3 pid = os.fork()
 4 
 5 if pid < 0:
 6   print("Error")
 7 elif pid == 0:
 8   print("Child process",os.getpid())
 9   os._exit(3)
10 else:
11   p,status = os.wait()  # 阻塞等待子进程退出
12   print("p : ",p)
13   # 还原退出状态
14   print("status:",os.WEXITSTATUS(status))
15   while True:
16     pass
wait 处理僵尸

2)创建二级子进程处理僵尸

  1. 父进程创建子进程,等待回收子进程
  2. 子进程创建二级子进程然后退出
  3. 二级子进程称为孤儿,和原来父进程一同执行事件
 1 import os
 2 from time import sleep
 3 
 4 def f1():
 5   for i in range(4):
 6     sleep(2)
 7     print("写代码")
 8 
 9 def f2():
10   for i in range(5):
11     sleep(1)
12     print("测代码")
13 
14 pid = os.fork()
15 if pid < 0:
16   print("Error")
17 elif pid == 0:
18   p = os.fork()  # 二级子进程
19   if p == 0:
20     f2()
21   else:
22     os._exit(0)  # 一级子进程退出
23 else:
24   os.wait() # 等一级子进程退出
25   f1()
二级子进程处理僵尸

3)通过信号处理子进程退出

原理: 子进程退出时会发送信号给父进程,如果父进程忽略子进程信号,则系统就会自动处理子进程退出。

方法: 使用signal模块在父进程创建子进程前写如下语句 :

import signal
signal.signal(signal.SIGCHLD,signal.SIG_IGN)

特点 : 非阻塞,不会影响父进程运行。可以处理所有子进程退出

 1 import signal
 2 import os
 3 
 4 # 子进程退出时父进程会忽略,此时子进程自动由系统处理
 5 signal.signal(signal.SIGCHLD,signal.SIG_IGN)
 6 
 7 pid = os.fork()
 8 
 9 if pid < 0:
10   pass
11 elif pid == 0:
12   print("Child pid:",os.getpid())
13 else:
14   while True:
15     pass
信号方法处理僵尸进程
原文地址:https://www.cnblogs.com/maplethefox/p/10989131.html