多進程編程及進程間的通訊多進程的優缺點進程(process)三態五態(三態的基礎上增長了新建態和終止態)進程優先級進程特徵孤兒進程殭屍進程要求理解多進程編程進程相關的函數多進程模塊Process()建立自定義繼承Process類進程池技術Pool函數進程間的通信(IPC)管道通信多進程管道傳輸數據示例消息隊列單進程示例多進程消息隊列傳遞數據共享內存信號通訊html
優勢node
缺點python
查看進程:ps -aux
查看進程樹:pstree
查看父進程:ps -ajx
git
標誌 | 名稱 | 說明 |
---|---|---|
S | 等待態 | 可中斷等待 |
D | 等待態 | 不可中斷等待 |
T | 等待態 | 暫停狀態 |
R | 運行態 | 包含就緒狀態 |
Z | 殭屍進程 | |
< | 高優先級 | |
N | 優先級較低 | |
l | 有子進程的 | |
s | 會話組組長 | |
+ | 前臺進程 |
做用:決定了一個進程的執行權限github
動態查看系統中的進程信息:top
,用< , >
翻頁web
使用指定的優先級運行程序編程
nice
: 指定運行的優先級windows
e.g. :nice -9 ./while.py
--->>以優先級-9運行安全
如何避免殭屍進程的產生數據結構
處理子進程的退出狀態
pid, status = os.wait()
功能:在父進程中堵塞等待子進程退出
返回值:
1 2 3 # 功能 : 建立新的進程 4 # 參數 : 無 5 # 返回值 : 失敗--->返回一個負數 6 # 成功--->在新的進程中返回 ‘0’ 7 # 在原有的進程中返回新的進程的PID號 8 import os 9 pid = os.fork() 10 pid = os.fork() 11 print(pid) 12 13 '''打印 14 9352 15 0 16 9353 17 '''
函數方法 | 參數 | 說明 |
---|---|---|
os.getpid() | 返回當前進程的PID號 | |
os.getppid() | 返回當前進程的父進程的PID號 | |
os._exit( status ) | 程序的退出狀態 | 進程退出 |
sys.exit( [ status ] ) | 數字:表示退出狀態,不寫默認爲 | 進程退出 |
import os pid = os.fork() if pid < 0: print("建立進程失敗") elif pid == 0: print("子進程個人真實PID爲:",os.getpid(),"個人父進程PID爲:",os.getppid()) else: print("我是父進程執行的代碼,當前的變量pid爲:",pid,"個人真實PID爲:",os.getpid()) '''打印內容'''''' 我是父進程執行的代碼,當前的變量pid爲: 10992 個人真實PID爲: 10991 子進程個人真實PID爲: 10992 個人父進程PID爲: 10991 ''''''打印內容''' # 若是pid 10992和子進程真實PID不一樣,那麼這個子進程就變成了孤兒進程
import multiprocessing
from multiprocessing import Process
功能:建立一個進程對象
參數
函數方法 | 說明 |
---|---|
p.start() | 啓動進程,target函數自動執行,此時進程被真正建立 |
p.join([timeout]) | 阻塞等待回收子進程,timeout爲超時時間 |
p.is_alive() | 判斷進程生命週期狀態,處於生命週期,返回布爾值 |
p.name() | 獲取進程名稱 |
p.pid() | 獲取進程 的pid |
p.daemon() | 默認狀態False,主進程退出不影響子進程。True :子進程隨着主進程結束 |
使用multiprocessing建立子進程,一樣子進程複製父進程的所有代碼,父子進程各自執行互不影響,父子進程有各自的運行空間
若是不使用join揮手子進程則子進程退出後會成爲殭屍進程
from multiprocessing import Process from time import sleep #帶參數的進程函數 def worker(sec,name): for i in range(3): sleep(sec) print("I'm %s"%name) print("I'm working...") p = Process(target = worker,args = (2,),\ kwargs = {'name':'Daivl'},name = "Worker") p.start() print("Process name:",p.name) #進程名稱 print("Process PID:",p.pid) #獲取進程PID #進程alive狀況 print("Process is alive:",p.is_alive()) p.join(3) print("==================")
繼承Process
編寫本身的__init__
,同時加載父類的__init__
方法
重寫run
方法,能夠經過生成的對象調用start自動運行
from import Process import time class ClockProcess(Process): def __init__(self,value): self.value = value super(ClockProcess,self).__init__() def run(self): for i in range(5): print("如今的時間是",time.ctime()) time.sleep(self.value) # 建立自定義進的類的對象 p =ClockProcess(2) # 自動調用run p.start() p.join()
產生緣由
原理
使用方法
Pool(Processes)
pool.apply_async(func, args, kwds)
功能:將時間放入進程池隊列
參數
返回值一個對象
pool.apply(func, args, kwds)
功能:將時間放入進程池隊列
參數
pool.close()
pool.join()
pool.map(func,iter)
功能:將要作的事件放入進程池
參數
返回值:屢次return的結果列
from multiprocessing import Process import time class ClockProcess(Process): def __init__(self,value): self.value = value super(ClockProcess,self).__init__() def run(self): for i in range(5): print("如今的時間是",time.ctime()) time.sleep(self.value) # 建立自定義進的類的對象 p =ClockProcess(2) # 自動調用run p.start() p.join()
進程間通信的方法有:管道,消息隊列,共享內存,信號,信號量,套接字
管道 | 消息隊列 | 共享內存 | |
---|---|---|---|
開闢空間 | 內存 | 內存 | 內存 |
讀寫方式 | 兩端讀寫[雙向/單向] | 先進先出 | 覆蓋以前的內容 |
效率 | 通常 | 通常 | 較高 |
應用 | 多用於父子進程 | 普遍靈活 | 須要注意互斥 |
通訊原理:在內存中開闢管道空間,生成管道操做對象,多個進程使用「同一個」管道對象進行操做,便可實現通訊
multiprocessing --> Pipe
fd1,fd2 = Pipe(duplex = True)
功能:建立管道
參數
返回值
fd.recv()
fd.send(data)
from multiprocessing import Process,Pipe import time,os # 建立管道對象 fd1, fd2 = Pipe() def fun(name): time.sleep(1) fd2.send(os.getppid()) jobs = [] # 建立5個子進程 for i in range(5): p = Process(target = fun,args = (i,)) jobs.append(p) p.start() for i in range(5): data = fd1.recv() print(data) for i in jobs: i.join()
隊列:先進先出,按照順序來
通訊原理:在內存中創建隊列數據結構模型。多個進程均可以經過隊列存入內容,取出內容的順序和存入的順序保持一致
建立隊列
q = Queue(maxsize = 0)
q.put(data, [block, timeout])
功能:像隊列存儲消息
參數
data = q.get([block, timeout])
功能:獲取隊列消息
參數
返回值:返回取出的內容
q.full()
:判斷隊列是否爲滿
q.empty()
:判斷隊列是否爲空
q.size()
:判斷隊列中的消息數量
q.close
:關閉隊列
#!《 單進程 》 from multiprocessing import Queue from time import sleep # 建立隊列,能夠放3條消息 q = Queue(3) # 存一條消息 q.put(1) sleep(0.5) # 判斷隊列是否爲空 print(q.empty()) q.put(2) # 判斷隊列是否滿 print(q.full()) q.put(3) # 輸出隊列消息數量 print(q.qsize()) # 輸出 print(q.get()) q.close()
from multiprocessing import Queue,Process from time import sleep # 建立隊列,能夠放3條消息 q = Queue(3) def fun1(): sleep(1) q.put({"a":1,"b":2}) def fun2(): sleep(2) print("收到消息",q.get()) p1 = Process(target = fun1) p2 = Process(target = fun2) p1.start() p2.start() p1.join() p2.join()
通訊原理:在內存中開闢一段空間,對多個進程可見,進程能夠寫入能夠讀,可是每次寫入的內容會覆蓋上一次的內容。
只能進行單個數據的發送
obj = Value(ctype, obj)
功能:開闢共享內存空間
參數
返回值:共享內存對象
obj.value
即共享內存值,對其修改便可修改內存
from multiprocessing import Value from time import sleep import os # 建立共享內存對象 money = Value('i',2000) # 操做共享內存 def deposite(): while True: i = int(input("請輸入:")) money.value = i sleep(0.05) def withdraw(): data = money.value while True: if data != money.value : data = money.value print(data) pid = os.fork() if pid == 0 : deposite() withdraw()
obj = Array(ctype, obj)
功能:開闢共享內存空間
參數:
返回值:返回共享內存對象,能夠遍歷
from multiprocessing import Array,Process from time import sleep import os # 開闢100字符內存空間,'c'表明字符,'i'表明整形 shm = Array('c',100) # 必須使用字節流 shm.value = "哈哈哈".encode() def fun1(): print(os.getpid(),"子進程1:",shm.value.decode()) shm.value = "夜夜夜".encode() def fun2(): sleep(1) print(os.getpid(), "子進程2:",shm.value.decode()) p1 = Process(target = fun1) p2 = Process(target = fun2) p1.start() p2.start() p1.join() p2.join()
一個進程向另外一個進程發送一個信號來傳遞某種信息,接受者根據傳遞的信息來作相應的事
$ kill -l
查看系統信號說明
$ kill -9 pid號
對進程發送信號
信號名稱 | 說明 | ||
---|---|---|---|
1) SIGHUP | 鏈接斷開 | ||
2) SIGINT | ctrl+c | ||
3) SIGQUIT | ctrl+\ | ||
20) SIGTSTP | ctrl+z | ||
9) SIGKILL | 終止進程 | ||
19) SIGSTOP | 暫停進程 | ||
26) SIGVTALRM | 時鐘信號 | ||
17) SIGCHLD | 子進程退出時給父進程發的信號 | ||
在Python中import signal
能夠獲取信號
os.kill(pid, sig)
功能:發送信號
參數
import os import signal os.kill(12345,signal.SIGKILL) #殺死進程
個性簽名:苟日新 日日新 又日新!
若是這篇文章對你有些幫助,記得在右下角點個「推薦」,拜謝!