定義:程序在計算機中的一次運行.python
系統中如何產生一個進程面試
進程基本概念編程
Linux查看進程ID:ps - aux多線程
查看進程樹: pstreeapp
五態(在三態基礎上增長新建和終止)dom
狀態查看命令: ps - aux --->STAT列async
S---等待態ide
R---執行態函數
Z---殭屍ui
+---前臺進程
l---有多線程
進程的運行特徵
面試要求:
什麼是進程,進程和程序有什麼區別?
進程有哪些狀態,狀態之間如何轉化?
pdi = os.fork()
功能:建立新的進程
返回值:整數,若是建立進程失敗返回一個負數,若是成功則在原有進程中返回新進程的PID,在新進程中返回0
注意:
fork進程代碼示例:
1 import os 2 from time import sleep 3 4 # 建立子進程 5 pid = os.fork() 6 7 if pid < 0: 8 print("Create process failed") 9 elif pid == 0: 10 # 只有子進程執行 11 sleep(3) 12 print("The new process") 13 else: 14 # 只有父進程執行 15 sleep(4) 16 print("The old process") 17 18 # 父子進程都執行 19 print("process test over")
fork進程代碼示例細節:
1 import os 2 from time import sleep 3 4 print("=========================") 5 a = 1 6 def fun(): 7 print("fun .... ") 8 9 pid = os.fork() 10 11 if pid < 0: 12 print("Create process failed") 13 elif pid == 0: 14 print("Child process") 15 print("a = ",a) # 從父進程空間拷貝了變量 16 fun() 17 a = 10000 # 只是修改了本身空間的a 18 else: 19 sleep(1) 20 print("Parent process") 21 print("a:",a) 22 23 print("All a ->",a)
os.getpid()
功能:獲取一個進程的PID值
返回值:返回當前進程的PID
os.getppid()
功能:獲取父進程的PID值
返回值:返回父進程PID
os._exit(status)
功能:結束一個進程
參數:進程的終止狀態
sys.exit([status])
功能:退出進程
參數:整數 表示退出狀態
字符串 表示退出時打印內容
獲取進程pid號代碼示例:
1 import os 2 from time import sleep 3 4 pid = os.fork() 5 6 if pid < 0: 7 print("Error") 8 elif pid == 0: 9 sleep(1) 10 print("Child PID:",os.getpid()) # 本身pid 11 print("Get parent PID:",os.getppid()) # 父pid 12 else: 13 print("Parent PID:", os.getpid()) # 本身pid 14 print("Get child PID:",pid)
進程退出代碼示例:
1 import os,sys 2 3 pid = os.fork() 4 5 # 父子進程退出不會影響對方繼續執行 6 if pid < 0: 7 print("Error") 8 elif pid == 0: 9 # os._exit(0) # 子進程退出 10 print("Child process") 11 else: 12 sys.exit("退出父進程") 13 print("Parent process")
特色:孤兒進程會被系統進程收養,此時系統進程就會成爲孤兒進程新的父進程,孤兒進程退出該進程會自動處理
特色:殭屍進程雖然結束,可是會存留部分PCD在內存中,大量的殭屍進程會浪費系統的內存資源
模擬殭屍進程產生以及處理示例:
1 import os,sys 2 import signal 3 4 # 忽略子進程的退出行爲,子進程退出自動由系統處理 5 signal.signal(signal.SIGCHLD,signal.SIG_IGN) 6 7 pid = os.fork() 8 if pid < 0: 9 print("Error") 10 elif pid == 0: 11 print("Child PID:",os.getpid()) 12 sys.exit(2) 13 else: 14 """ 15 os.wait() 處理殭屍 16 """ 17 # pid,status = os.wait() 18 # print("pid:",pid) 19 # print('status:',os.WEXITSTATUS(status)) 20 while True: # 讓父進程不退出 21 pass
代碼示例:
1 import os 2 from time import sleep 3 4 def f1(): 5 for i in range(3): 6 sleep(2) 7 print("寫代碼") 8 9 def f2(): 10 for i in range(2): 11 sleep(4) 12 print("測代碼") 13 14 pid = os.fork() 15 if pid == 0: 16 p = os.fork() # 建立二級子進程 17 if p == 0: 18 f1() 19 else: 20 os._exit(0) # 一級子進程退出 21 else: 22 os.wait() # 等待回收一級子進程 23 f2()
經過信號處理子進程退出
原理:子進程退出時會發送信號給父進程,若是父進程忽略子進程信號,則系統就會自動處理子進程退出
方法:使用signal模塊在父進程建立子進程前寫以下語句:
import signal
signal.signal(signal.SIGCHLD,signal.SIG_IGN)
特色:非阻塞,不會影響父進程運行,能夠處理全部子進程退出
Process()
功能 : 建立進程對象
參數 : target 綁定要執行的目標函數
args 元組,用於給target函數位置傳參
kwargs 字典,給target函數鍵值傳參
p.start()
功能 : 啓動進程
注意:啓動進程此時target綁定函數開始執行,該函數做爲子進程執行內容,此時進程真正被建立
p.join([timeout]) 功能:阻塞等待回收進程 參數:超時時間
注意:
子進程只運行target綁定的函數部分,其他內容均是父進程執行內容。
multiprocessing中父進程每每只用來建立子進程回收子進程,具體事件由子進程完成。
multiprocessing建立的子進程中沒法使用標準輸入
p.name 進程名稱
p.pid 對應子進程的PID號
p.is_alive() 查看子進程是否在生命週期
p.daemon 設置父子進程的退出關係
進程對象代碼示例:
1 from multiprocessing import Process 2 import time 3 4 def tm(): 5 for i in range(3): 6 print(time.ctime()) 7 time.sleep(2) 8 9 p = Process(target = tm,name = 'Tarena') 10 11 # 父進程退出,其全部子進程也退出 12 p.daemon = True 13 14 p.start() # 進程真正產生 15 16 print("Name:",p.name) # 進程名 17 print("PID:",p.pid) # pid號 18 print("is alive:",p.is_alive()) # 是否在生命週期
自定義進程類代碼示例:
1 from multiprocessing import Process 2 from time import * 3 4 # 自定義進程類 5 class MyProcess(Process): 6 def __init__(self,value): 7 self.value = value 8 super().__init__() # 加載父類init 9 10 def f1(self): 11 print("步驟1") 12 def f2(self): 13 print("步驟2") 14 15 # 做爲流程啓動函數 16 def run(self): 17 for i in range(self.value): 18 self.f1() 19 self.f2() 20 21 if __name__ == '__main__': 22 p = MyProcess(2) 23 p.start() 24 p.join()
建立必定數量的進程來處理事件,事件處理完進程不退出而是繼續處理其餘時間,直到全部事件全都處理完畢統一銷燬.增長進程的重複利用,下降資源消耗.
1.建立進程池對象,放入適當的進程
from multiprocessing import Pool
Pool(processes)
功能: 建立進程池對象
參數: 指定進程數量,默認根據系統自動斷定
2.將事件加入進程池隊列執行
pool.apply_async(func,args,kwds)
功能: 使用進程池執行 func事件
參數: func 事件函數
args 元組 給func按位置傳參
kwds 字典 給func按照鍵值傳參
返回值: 返回函數事件對象
3.關閉進程池
pool.close()
功能: 關閉進程池
4.回收進程池中進程
pool.join()
功能: 回收進程池中進程
進程池代碼示例:
1 from multiprocessing import Pool 2 from time import sleep,ctime 3 4 # 進程池事件 5 def worker(msg): 6 sleep(2) 7 print(ctime(),'--',msg) 8 9 # 建立進程池 10 pool = Pool(4) 11 12 # 向進程池隊列中添加事件 13 for i in range(10): 14 msg = "Tedu %d"%i 15 pool.apply_async(func=worker,args=(msg,)) 16 17 # 關閉進程池 18 pool.close() 19 20 # 回收進程池 21 pool.join()
在內存中開闢管道空間,生成管道操做對象,多個進程使用同一管道對象,進行讀寫便可實現通訊
from multiprocessing import Pipe
fd1,fd2 = Pipe(duplex = True) 功能: 建立管道 參數:默認表示雙向管道 若是爲False 表示單向管道 返回值:表示管道兩端的讀寫對象 若是是雙向管道都可讀寫 若是是單向管道fd1只讀 fd2只寫 fd.recv() 功能 : 從管道獲取內容 返回值:獲取到的數據 fd.send(data) 能夠是任何內容,如:整數,浮點數,字符串等 功能: 向管道寫入內容 參數: 要寫入的數據
管道操做
注意:
管道操做代碼示例:
1 from multiprocessing import Process,Pipe 2 3 # 建立管道對象 4 # 參數False 表示fd1 只能 recv , fd2 只能 send 5 fd1,fd2 = Pipe() 6 7 # APP1可使用app2提供的信息登陸 8 def app1(): 9 print("啓動app1,請登陸") 10 print("請求app2受權") 11 # 寫管道 12 fd1.send("app1 能夠用你的帳號登陸嗎?") 13 data = fd1.recv() 14 if data: 15 print("登陸成功:",data) 16 17 def app2(): 18 request = fd2.recv() # 阻塞等待讀取管道 19 print(request) 20 fd2.send(('Joy','123')) # 發送python數據類型 21 22 p1 = Process(target=app1) 23 p2 = Process(target=app2) 24 p1.start() 25 p2.start() 26 p1.join() 27 p2.join() 28 29 代碼示例
在內存中創建隊列模型,進程經過隊列將消息存入,或者從隊列取出完成進程間通訊.
from multiprocessing import Queue q = Queue(maxsize=0) 功能: 建立隊列對象 參數:最多存放消息個數 返回值:隊列對象 q.put(data,[block,timeout]) 功能:向隊列存入消息 參數:data 要存入的內容 block 設置是否阻塞 False爲非阻塞 timeout 超時檢測 q.get([block,timeout]) 功能:從隊列取出消息 參數:block 設置是否阻塞 False爲非阻塞 timeout 超時檢測 返回值: 返回獲取到的內容 q.full() 判斷隊列是否爲滿 q.empty() 判斷隊列是否爲空 q.qsize() 獲取隊列中消息個數 q.close() 關閉隊列
消息隊列代碼示例:
1 from multiprocessing import Queue,Process 2 from time import sleep 3 from random import randint 4 5 # 建立隊列 6 q = Queue(5) # 最大存儲5個消息 7 8 def request(): 9 for i in range(10): 10 x = randint(1,100) 11 y = randint(1,100) 12 q.put((x,y)) # 寫消息隊列 13 print("=============") 14 15 def handle(): 16 while not q.empty(): 17 data = q.get() # 讀消息隊列 18 print("x + y = ",data[0]+data[1]) 19 sleep(2) 20 21 p1 = Process(target=request) 22 p2 = Process(target=handle) 23 p1.start() 24 p2.start() 25 p1.join() 26 p2.join() 27 28 代碼示例
from multiprocessing import Value,Array obj = Value(ctype,data) 功能 : 開闢共享內存 參數 : ctype 表示共享內存空間類型 'i' 'f' 'c' data 共享內存空間初始數據 返回值:共享內存對象 obj.value 對該屬性的修改查看即對共享內存讀寫 obj = Array(ctype,data) 功能: 開闢共享內存空間 參數: ctype 表示共享內存數據類型 data 整數則表示開闢空間的大小,其餘數據類型表示開闢空間存放的初始化數據 返回值:共享內存對象 Array共享內存讀寫: 經過遍歷obj能夠獲得每一個值,直接能夠經過索引序號修改任意值。 * 可使用obj.value直接打印共享內存中的字節串
共享內存代碼示例:
注意:共享內存中只能有一個值
1 from multiprocessing import Process,Value 2 import time 3 import random 4 5 # 建立共享內存 6 money = Value('i',5000) 7 8 def man(): 9 for i in range(30): 10 time.sleep(0.2) 11 # 修改共享內存 12 money.value += random.randint(1,1000) 13 14 def girl(): 15 for i in range(30): 16 time.sleep(0.15) 17 money.value -= random.randint(100,800) 18 19 p1 = Process(target=man) 20 p2 = Process(target=girl) 21 p1.start() 22 p2.start() 23 p1.join() 24 p2.join() 25 print("一個月餘額:",money.value) #讀取共享內存
共享內存存放列表,字節串:
1 from multiprocessing import Process,Array 2 3 # 建立共享內存,初始數據 [1,2,3,4] 4 # shm = Array('i',[1,2,3,4]) 5 # shm = Array('i',4) # 開闢4個整形的列表空間 6 shm = Array('c',b'hello') 7 8 def fun(): 9 # 共享內存對象能夠迭代 10 for i in shm: 11 print(i) 12 shm[0] = b'H' # 修改共享內存 13 14 p = Process(target=fun) 15 p.start() 16 p.join() 17 for i in shm: 18 print(i) 19 print(shm.value) # 總體打印字節串
給定一個數量對多個進程可見.多個進程均可以操做改數量增減,並根據數量值決定本身的行爲
from multiprocessing import Semaphore sem = Semaphore(num) 功能 : 建立信號量對象 參數 : 信號量的初始值 返回值 : 信號量對象 sem.acquire() 將信號量減1 當信號量爲0時阻塞 sem.release() 將信號量加1 sem.get_value() 獲取信號量數量
信號量代碼示例:
注意: 信號量能夠當作是一種資源,執行任務須要消耗信號量資源,
這樣能夠控制進程執行行爲
1 from multiprocessing import Process,Semaphore 2 from time import sleep 3 import os 4 5 # 建立信號量資源 6 sem = Semaphore(3) 7 8 # 任務函數 (系統中最多可以同時運行三個該任務) 9 def handle(): 10 sem.acquire() # 消耗一個信號量 11 print("%s執行任務"%os.getpid()) 12 sleep(2) 13 print("%s 拯救了宇宙"%os.getpid()) 14 sem.release() # 增長一個信號量 15 16 jobs = [] 17 for i in range(10): 18 p = Process(target = handle) 19 jobs.append(p) 20 p.start() 21 22 for i in jobs: 23 i.join()