網絡基礎之 併發編程之進程,多路複用,multiprocess模塊

併發
1. 背景知識
2. 什麼是進程
3. 進程調度
4. 併發與並行
5 同步\異步\阻塞\非阻塞(重點)
6.multiprocess模塊
7.殭屍進程與孤兒進程

1.背景知識

一操做系統的做用:
1:隱藏醜陋複雜的硬件接口,提供良好的抽象接口
2:管理、調度進程,而且將多個進程對硬件的競爭變得有序

二 多道技術:
1.產生背景:針對單核,實現併發
ps:如今的主機通常是多核,那麼每一個核都會利用多道技術有4個cpu,運行於cpu1的某個程序遇到io阻塞,會等到io結束再從新調度,
會被調度到4個cpu中的任意一個,具體由操做系統調度算法決定。

2.空間上的複用:如內存中同時有多道程序

3.時間上的複用:複用一個cpu的時間片
強調:遇到io切,佔用cpu時間過長也切,核心在於切以前將進程的狀態保存下來,這樣才能保證下次切換回來時,能基於上次切走的位置繼續運行


2. 什麼是進程

狹義定義:進程是正在運行的程序的實例(an instance of a computer program that is being executed)。
廣義定義:進程是一個具備必定獨立功能的程序關於某個數據集合的一次運行活動。它是操做系統動態執行的基本單元,在傳統的操做系統中,進程既是基本的分配單元,也是基本的執行單元。

進程的概念:
第一,進程是一個實體。每個進程都有它本身的地址空間,通常狀況下,包括文本區域(text region)(python的文件)、數據區域(data region)(python文件中定義的一些變量數據)和堆棧(stack region)。
文本區域存儲處理器執行的代碼;數據區域存儲變量和進程執行期間使用的動態分配的內存;堆棧區域存儲着活動過程調用的指令和本地變量。

第二,進程是一個「執行中的程序」。程序是一個沒有生命的實體,只有處理器賦予程序生命時(操做系統執行之),它才能成爲一個活動的實體,咱們稱其爲進程。[3]
進程是操做系統中最基本、重要的概念。是多道程序系統出現後,爲了刻畫系統內部出現的動態狀況,描述系統內部各道程序的活動規律引進的一個概念,全部多道程序設計操做系統都創建在進程的基礎上。

進程的特徵
動態性:進程的實質是程序在多道程序系統中的一次執行過程,進程是動態產生,動態消亡的。
併發性:任何進程均可以同其餘進程一塊兒併發執行
獨立性:進程是一個能獨立運行的基本單位,同時也是系統分配資源和調度的獨立單位;
異步性:因爲進程間的相互制約,使進程具備執行的間斷性,即進程按各自獨立的、不可預知的速度向前推動
結構特徵:進程由程序、數據和進程控制塊三部分組成。

多個不一樣的進程能夠包含相同的程序:一個程序在不一樣的數據集裏就構成不一樣的進程,能獲得不一樣的結果;可是執行過程當中,程序不能發生改變。

程序和進程的區別

程序是指令和數據的有序集合,其自己沒有任何運行的含義,是一個靜態的概念。
而進程是程序在處理機上的一次執行過程,它是一個動態的概念。
程序能夠做爲一種軟件資料長期存在,而進程是有必定生命期的。
程序是永久的,進程是暫時的。

3. 進程調度
1.先來先服務(FCFS)調度算法是一種最簡單的調度算法,該算法既可用於做業調度,也可用於進程調度。FCFS算法比較有利於長做業(進程),而不利於短做業(進程)
2.短做業(進程)優先調度算法(SJ/PF)是指對短做業或短進程優先調度的算法,該算法既可用於做業調度,也可用於進程調度。但其對長做業不利;不能保證緊迫性做業(進程)被及時處理;做業的長短只是被估算出來的
3.時間片輪轉(Round Robin,RR)法的基本思路是讓每一個進程在就緒隊列中的等待時間與享受服務的時間成比例。在時間片輪轉法中,須要將CPU的處理時間分紅固定大小的時間片,例如,幾十毫秒至幾百毫秒
4.多級反饋隊列調度算法,沒必要事先知道各類進程所需的執行時間,並且還能夠知足各類類型進程的須要,於是它是目前被公認的一種較好的進程調度算法。


4. 併發與並行
不管是並行仍是併發,在用戶看來都是'同時'運行的,無論是進程仍是線程,都只是一個任務而已,真是幹活的是cpu,cpu來作這些任務,而一個cpu同一時刻只能執行一個任務
併發:是僞並行,即看起來是同時運行。單個cpu+多道技術就能夠實現併發,(並行也屬於併發)
並行:同時運行,只有具有多個cpu才能實現並行

多道技術概念回顧:內存中同時存入多道(多個)程序,cpu從一個進程快速切換到另一個,使每一個進程各自運行幾十或幾百毫秒,
這樣,雖然在某一個瞬間,一個cpu只能執行一個任務,但在1秒內,cpu卻能夠運行多個進程,這就給人產生了並行的錯覺,即僞並行,以此來區分多處理器操做系統的真正硬件並行(多個cpu共享同一個物理內存)


5.同步\異步\阻塞\非阻塞(重點)
1.進程狀態介紹
(1)就緒(Ready)狀態當進程已分配到除CPU之外的全部必要的資源,只要得到處理機即可當即執行,這時的進程狀態稱爲就緒狀態。
(2)執行/運行(Running)狀態當進程已得到處理機,其程序正在處理機上執行,此時的進程狀態稱爲執行狀態。
(3)阻塞(Blocked)狀態正在執行的進程,因爲等待某個事件發生而沒法執行時,便放棄處理機而處於阻塞狀態。引發進程阻塞的事件可有多種,例如,等待I/O完成、申請緩衝區不能知足、等待信件(信號)等。
    事件請求:input、sleep、文件輸入輸出、recv、accept等
    事件發生:sleep、input等完成了
    時間片到了以後有回到就緒狀態,這三個狀態不斷的在轉換

2.同步異步

1.所謂同步就是一個任務的完成須要依賴另一個任務時,只有等待被依賴的任務完成後,依賴的任務才能算完成,這是一種可靠的任務序列
2.所謂異步是不須要等待被依賴的任務完成,只是通知被依賴的任務要完成什麼工做,依賴的任務也當即執行,只要本身完成了整個任務就算完成了。
至於被依賴的任務最終是否真正完成,依賴它的任務沒法肯定,因此它是不可靠的任務序列。

3.阻塞與非阻塞
阻塞和非阻塞這兩個概念與程序(線程)等待消息通知(無所謂同步或者異步)時的狀態有關。
也就是說阻塞與非阻塞主要是程序(線程)等待消息通知時的狀態角度來講的


4.同步/異步與阻塞和非阻塞

同步阻塞形式:效率最低。拿上面的例子來講,就是你專心排隊,什麼別的事都不作。

異步阻塞形式:若是在排隊取餐的人採用的是異步的方式去等待消息被觸發(通知),也就是領了一張小紙條,假如在這段時間裏他不能作其它的事情,就在那坐着等着,不能玩遊戲等,那麼很顯然,這我的被阻塞在了這個等待的操做上面;
異步操做是能夠被阻塞住的,只不過它不是在處理消息時阻塞,而是在等待消息通知時被阻塞。

同步非阻塞形式:其實是效率低下的。想象一下你一邊打着電話一邊還須要擡頭看到底隊伍排到你了沒有,若是把打電話和觀察排隊的位置當作是程序的兩個操做的話,
這個程序須要在這兩種不一樣的行爲之間來回的切換,效率可想而知是低下的。

異步非阻塞形式:效率更高,由於打電話是你(等待者)的事情,而通知你則是櫃檯(消息觸發機制)的事情,程序沒有在兩種不一樣的操做中來回切換。

tips:不少人會把同步和阻塞混淆,是由於不少時候同步操做會以阻塞的形式表現出來,一樣的,不少人也會把異步和非阻塞混淆,由於異步操做通常都不會在真正的IO操做處被阻塞。


6.multiprocess模塊
1.process模塊介紹
process模塊是一個建立進程的模塊,藉助這個模塊,就能夠完成進程的建立。

主進程建立的子進程是異步執行的,那麼咱們就驗證一下,而且看一會兒進程和主進程(也就是父進程)的ID號(講一下pid和ppid,使用pycharm舉例),來看看是不是父子關係。
from multiprocessing import Process import time,os def func1(): time.sleep(2) print("我是func1") print("主進程>>",os.getpid()) def func2(): time.sleep(2) print("我是func2") print("子進程>>",os.getpid()) print("子進程的父進程>>", os.getppid()) if __name__ == "__main__": p = Process(target=func2) p.start() func1() print("主進程的父進程>>",os.getppid())

Process類中參數的介紹:
參數介紹:
1 group參數未使用,值始終爲None
2 target表示調用對象,即子進程要執行的任務
3 args表示調用對象的位置參數元組,args=(1,2,'egon',)
4 kwargs表示調用對象的字典,kwargs={'name':'egon','age':18}
5 name爲子進程的名稱

給要執行的函數傳參數:
from multiprocessing import Process
import time
def func(m,n):
    print(m)
    time.sleep(1)
    print(n)
if __name__ == '__main__':
    p1 = Process(target=func,args=(10,20))
    p1.start()

 

Process類中各方法的介紹:
1 p.start():啓動進程,並調用該子進程中的p.run()
2 p.run():進程啓動時運行的方法,正是它去調用target指定的函數,咱們自定義類的類中必定要實現該方法
3 p.terminate():強制終止進程p,不會進行任何清理操做,若是p建立了子進程,該子進程就成了殭屍進程,使用該方法須要特別當心這種狀況。若是p還保存了一個鎖那麼也將不會被釋放,進而致使死鎖
4 p.is_alive():若是p仍然運行,返回True
5 p.join([timeout]):主線程等待p終止(強調:是主線程處於等的狀態,而p是處於運行的狀態)。
timeout是可選的超時時間,須要強調的是,p.join只能join住start開啓的進程,而不能join住run開啓的進程

 Process類中自帶封裝的各屬性的介紹
1 p.daemon:默認值爲False,若是設爲True,表明p爲後臺運行的守護進程,當p的父進程終止時,p也隨之終止,而且設定爲True後,p不能建立本身的新進程,必須在p.start()以前設置
2 p.name:進程的名稱
3 p.pid:進程的pid
4 p.exitcode:進程在運行時爲None、若是爲–N,表示被信號N結束(瞭解便可)
5 p.authkey:進程的身份驗證鍵,默認是由os.urandom()隨機生成的32字符的字符串。這個鍵的用途是爲涉及網絡鏈接的底層進程間通訊提供安全性,這類鏈接只有在具備相同的身份驗證鍵時才能成功(瞭解便可)

2.Process類的使用

進程的建立第二種方法(繼承)
from multiprocessing import Process import time class myprocess(Process): def __init__(self,n): super().__init__() self.n = n def run(self): #想要定義功能,必須採用run的名字,由於target會調用名稱爲run的函數 time.sleep(2) print("我是run") if __name__ == '__main__': p1 = myprocess(10) p1.start()

進程之間的數據是隔離的:
驗證明例:
from multiprocessing import Process import time,os num = 100 def func(): global num num -= 1 print("子程序pid:%s,子程序的父程序%s,num=%s"%(os.getpid(),os.getppid(),num)) lis = [] if __name__ == '__main__': for i in range(10): p = Process(target=func) p.start() lis.append(p) for el in lis: el.join() print("主程序pid:%s,num=%s"%(os.getpid(),num))

進程對象的其餘方法一:terminate,is_alive

from multiprocessing import Process import time import random class Piao(Process): def __init__(self,name): super().__init__() self.name = name # def run(self): print('%s is 玩泥巴' %self.name) # s = input('???') #別忘了再pycharm下子進程中不能input輸入,會報錯EOFError: EOF when reading a line,由於子進程中沒有像咱們主進程這樣的在pycharm下的控制檯能夠輸入東西的地方 time.sleep(2) print('%s is 玩泥巴結束' %self.name) if __name__ == '__main__': p1 = Piao("尼古拉斯") p1.start() time.sleep() p1.terminate()#關閉進程,不會當即關閉,有個等着操做系統去關閉這個進程的時間,因此is_alive馬上查看的結果可能仍是存活,可是稍微等一會,就被關掉了 print(p1.is_alive()) #結果爲True print('等會。。。。') time.sleep(1) print(p1.is_alive()) #結果爲False

 

7.殭屍進程與孤兒進程(簡單瞭解 一下就能夠啦)  殭屍進程:一個進程使用fork建立子進程,若是子進程退出,而父進程並無調用wait或waitpid獲取子進程的狀態信息,那麼子進程的進程描述符仍然保存在系統中。這種進程稱之爲僵死進程。詳解以下咱們知道在unix/linux中,正常狀況下子進程是經過父進程建立的,子進程在建立新的進程。子進程的結束和父進程的運行是一個異步過程,即父進程永遠沒法預測子進程到底何時結束,若是子進程一結束就馬上回收其所有資源,那麼在父進程內將沒法獲取子進程的狀態信息。    孤兒進程:一個父進程退出,而它的一個或多個子進程還在運行,那麼那些子進程將成爲孤兒進程。孤兒進程將被init進程(進程號爲1)所收養,並由init進程對它們完成狀態收集工做。孤兒進程是沒有父進程的進程,孤兒進程這個重任就落到了init進程身上,init進程就好像是一個民政局,專門負責處理孤兒進程的善後工做
相關文章
相關標籤/搜索