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
信號方法處理僵屍進程

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM