理論知識 操作系統背景知識 顧名思義,進程即正在執行的一個過程。進程是對正在運行程式的一個抽象。 進程的概念起源於操作系統,是操作系統最核心的概念,也是操作系統提供的最古老也是最重要的抽象概念之一。操作系統的其他所有內容都是圍繞進程的概念展開的。 所以想要真正瞭解進程,必須事先瞭解操作系統,點擊進入 ...
理論知識
操作系統背景知識
顧名思義,進程即正在執行的一個過程。進程是對正在運行程式的一個抽象。
進程的概念起源於操作系統,是操作系統最核心的概念,也是操作系統提供的最古老也是最重要的抽象概念之一。操作系統的其他所有內容都是圍繞進程的概念展開的。
所以想要真正瞭解進程,必須事先瞭解操作系統,點擊進入
PS:即使可以利用的cpu只有一個(早期的電腦確實如此),也能保證支持(偽)併發的能力。將一個單獨的cpu變成多個虛擬的cpu(多道技術:時間多路復用和空間多路復用+硬體上支持隔離),沒有進程的抽象,現代電腦將不復存在。
必備的理論基礎:
#一 操作系統的作用: 1:隱藏醜陋複雜的硬體介面,提供良好的抽象介面 2:管理、調度進程,並且將多個進程對硬體的競爭變得有序 #二 多道技術: 1.產生背景:針對單核,實現併發 ps: 現在的主機一般是多核,那麼每個核都會利用多道技術 有4個cpu,運行於cpu1的某個程式遇到io阻塞,會等到io結束再重新調度,會被調度到4個 cpu中的任意一個,具體由操作系統調度演算法決定。 2.空間上的復用:如記憶體中同時有多道程式 3.時間上的復用:復用一個cpu的時間片 強調:遇到io切,占用cpu時間過長也切,核心在於切之前將進程的狀態保存下來,這樣 才能保證下次切換回來時,能基於上次切走的位置繼續運行
什麼是進程
進程(Process)是電腦中的程式關於某數據集合上的一次運行活動,是系統進行資源分配和調度的基本單位,是操作系統結構的基礎。在早期面向進程設計的電腦結構中,進程是程式的基本執行實體;在當代面向線程設計的電腦結構中,進程是線程的容器。程式是指令、數據及其組織形式的描述,進程是程式的實體。
狹義定義:進程是正在運行的程式的實例(an instance of a computer program that is being executed)。 廣義定義:進程是一個具有一定獨立功能的程式關於某個數據集合的一次運行活動。它是操作系統動態執行的基本單元,在傳統的操作系統中,進程既是基本的分配單元,也是基本的執行單元。第一,進程是一個實體。每一個進程都有它自己的地址空間,一般情況下,包括文本區域(text region)、數據區域(data region)和堆棧(stack region)。文本區域存儲處理器執行的代碼;數據區域存儲變數和進程執行期間使用的動態分配的記憶體;堆棧區域存儲著活動過程調用的指令和本地變數。 第二,進程是一個“執行中的程式”。程式是一個沒有生命的實體,只有處理器賦予程式生命時(操作系統執行之),它才能成為一個活動的實體,我們稱其為進程。[3] 進程是操作系統中最基本、重要的概念。是多道程式系統出現後,為了刻畫系統內部出現的動態情況,描述系統內部各道程式的活動規律引進的一個概念,所有多道程式設計操作系統都建立在進程的基礎上。進程的概念
從理論角度看,是對正在運行的程式過程的抽象;
從實現角度看,是一種數據結構,目的在於清晰地刻畫動態系統的內在規律,有效管理和調度進入電腦系統主存儲器運行的程式。
操作系統引入進程的概念的原因
動態性:進程的實質是程式在多道程式系統中的一次執行過程,進程是動態產生,動態消亡的。
併發性:任何進程都可以同其他進程一起併發執行
獨立性:進程是一個能獨立運行的基本單位,同時也是系統分配資源和調度的獨立單位;
非同步性:由於進程間的相互制約,使進程具有執行的間斷性,即進程按各自獨立的、不可預知的速度向前推進
結構特征:進程由程式、數據和進程式控制制塊三部分組成。
多個不同的進程可以包含相同的程式:一個程式在不同的數據集里就構成不同的進程,能得到不同的結果;但是執行過程中,程式不能發生改變。
進程的特征
程式是指令和數據的有序集合,其本身沒有任何運行的含義,是一個靜態的概念。
而進程是程式在處理機上的一次執行過程,它是一個動態的概念。
程式可以作為一種軟體資料長期存在,而進程是有一定生命期的。
程式是永久的,進程是暫時的。
進程與程式中的區別
註意:同一個程式執行兩次,就會在操作系統中出現兩個進程,所以我們可以同時運行一個軟體,分別做不同的事情也不會混亂。
進程調度
要想多個進程交替運行,操作系統必須對這些進程進行調度,這個調度也不是隨即進行的,而是需要遵循一定的法則,由此就有了進程的調度演算法。
先來先服務(FCFS)調度演算法是一種最簡單的調度演算法,該演算法既可用於作業調度,也可用於進程調度。FCFS演算法比較有利於長作業(進程),而不利於短作業(進程)。由此可知,本演算法適合於CPU繁忙型作業,而不利於I/O繁忙型的作業(進程)。先來先服務調度演算法
短作業(進程)優先調度演算法(SJ/PF)是指對短作業或短進程優先調度的演算法,該演算法既可用於作業調度,也可用於進程調度。但其對長作業不利;不能保證緊迫性作業(進程)被及時處理;作業的長短只是被估算出來的。短作業優先調度演算法
時間片輪轉(Round Robin,RR)法的基本思路是讓每個進程在就緒隊列中的等待時間與享受服務的時間成比例。在時間片輪轉法中,需要將CPU的處理時間分成固定大小的時間片,例如,幾十毫秒至幾百毫秒。如果一個進程在被調度選中之後用完了系統規定的時間片,但又未完成要求的任務,則它自行釋放自己所占有的CPU而排到就緒隊列的末尾,等待下一次調度。同時,進程調度程式又去調度當前就緒隊列中的第一個進程。 顯然,輪轉法只能用來調度分配一些可以搶占的資源。這些可以搶占的資源可以隨時被剝奪,而且可以將它們再分配給別的進程。CPU是可搶占資源的一種。但印表機等資源是不可搶占的。由於作業調度是對除了CPU之外的所有系統硬體資源的分配,其中包含有不可搶占資源,所以作業調度不使用輪轉法。 在輪轉法中,時間片長度的選取非常重要。首先,時間片長度的選擇會直接影響到系統的開銷和響應時間。如果時間片長度過短,則調度程式搶占處理機的次數增多。這將使進程上下文切換次數也大大增加,從而加重系統開銷。反過來,如果時間片長度選擇過長,例如,一個時間片能保證就緒隊列中所需執行時間最長的進程能執行完畢,則輪轉法變成了先來先服務法。時間片長度的選擇是根據系統對響應時間的要求和就緒隊列中所允許最大的進程數來確定的。 在輪轉法中,加入到就緒隊列的進程有3種情況: 一種是分給它的時間片用完,但進程還未完成,回到就緒隊列的末尾等待下次調度去繼續執行。 另一種情況是分給該進程的時間片並未用完,只是因為請求I/O或由於進程的互斥與同步關係而被阻塞。當阻塞解除之後再回到就緒隊列。 第三種情況就是新創建進程進入就緒隊列。 如果對這些進程區別對待,給予不同的優先順序和時間片從直觀上看,可以進一步改善系統服務質量和效率。例如,我們可把就緒隊列按照進程到達就緒隊列的類型和進程被阻塞時的阻塞原因分成不同的就緒隊列,每個隊列按FCFS原則排列,各隊列之間的進程享有不同的優先順序,但同一隊列內優先順序相同。這樣,當一個進程在執行完它的時間片之後,或從睡眠中被喚醒以及被創建之後,將進入不同的就緒隊列。時間片輪轉法
前面介紹的各種用作進程調度的演算法都有一定的局限性。如短進程優先的調度演算法,僅照顧了短進程而忽略了長進程,而且如果並未指明進程的長度,則短進程優先和基於進程長度的搶占式調度演算法都將無法使用。 而多級反饋隊列調度演算法則不必事先知道各種進程所需的執行時間,而且還可以滿足各種類型進程的需要,因而它是目前被公認的一種較好的進程調度演算法。在採用多級反饋隊列調度演算法的系統中,調度演算法的實施過程如下所述。 (1) 應設置多個就緒隊列,併為各個隊列賦予不同的優先順序。第一個隊列的優先順序最高,第二個隊列次之,其餘各隊列的優先權逐個降低。該演算法賦予各個隊列中進程執行時間片的大小也各不相同,在優先權愈高的隊列中,為每個進程所規定的執行時間片就愈小。例如,第二個隊列的時間片要比第一個隊列的時間片長一倍,……,第i+1個隊列的時間片要比第i個隊列的時間片長一倍。 (2) 當一個新進程進入記憶體後,首先將它放入第一隊列的末尾,按FCFS原則排隊等待調度。當輪到該進程執行時,如它能在該時間片內完成,便可準備撤離系統;如果它在一個時間片結束時尚未完成,調度程式便將該進程轉入第二隊列的末尾,再同樣地按FCFS原則等待調度執行;如果它在第二隊列中運行一個時間片後仍未完成,再依次將它放入第三隊列,……,如此下去,當一個長作業(進程)從第一隊列依次降到第n隊列後,在第n 隊列便採取按時間片輪轉的方式運行。 (3) 僅當第一隊列空閑時,調度程式才調度第二隊列中的進程運行;僅當第1~(i-1)隊列均空時,才會調度第i隊列中的進程運行。如果處理機正在第i隊列中為某進程服務時,又有新進程進入優先權較高的隊列(第1~(i-1)中的任何一個隊列),則此時新進程將搶占正在運行進程的處理機,即由調度程式把正在運行的進程放回到第i隊列的末尾,把處理機分配給新到的高優先權進程。多級反饋隊列
進程的並行與併發
並行 : 並行是指兩者同時執行,比如賽跑,兩個人都在不停的往前跑;(資源夠用,比如三個線程,四核的CPU )
併發 : 併發是指資源有限的情況下,兩者交替輪流使用資源,比如一段路(單核CPU資源)同時只能過一個人,A走一段後,讓給B,B用完繼續給A ,交替使用,目的是提高效率。
區別:
並行是從微觀上,也就是在一個精確的時間片刻,有不同的程式在執行,這就要求必須有多個處理器。
併發是從巨集觀上,在一個時間段上可以看出是同時執行的,比如一個伺服器同時處理多個session。
同步非同步阻塞非阻塞
狀態介紹
在瞭解其他概念之前,我們首先要瞭解進程的幾個狀態。在程式運行的過程中,由於被操作系統的調度演算法控制,程式會進入幾個狀態:就緒,運行和阻塞。
(1)就緒(Ready)狀態
當進程已分配到除CPU以外的所有必要的資源,只要獲得處理機便可立即執行,這時的進程狀態稱為就緒狀態。
(2)執行/運行(Running)狀態當進程已獲得處理機,其程式正在處理機上執行,此時的進程狀態稱為執行狀態。
(3)阻塞(Blocked)狀態正在執行的進程,由於等待某個事件發生而無法執行時,便放棄處理機而處於阻塞狀態。引起進程阻塞的事件可有多種,例如,等待I/O完成、申請緩衝區不能滿足、等待信件(信號)等。
同步和非同步
所謂同步就是一個任務的完成需要依賴另外一個任務時,只有等待被依賴的任務完成後,依賴的任務才能算完成,這是一種可靠的任務序列
。要麼成功都成功,失敗都失敗,兩個任務的狀態可以保持一致。
所謂非同步是不需要等待被依賴的任務完成,只是通知被依賴的任務要完成什麼工作,依賴的任務也立即執行,只要自己完成了整個任務就算完成了
。至於被依賴的任務最終是否真正完成,依賴它的任務無法確定,所以它是不可靠的任務序列
。
比如我去銀行辦理業務,可能會有兩種方式:
第一種 :選擇排隊等候;
第二種 :選擇取一個小紙條上面有我的號碼,等到排到我這一號時由櫃臺的人通知我輪到我去辦理業務了;
第一種:前者(排隊等候)就是同步等待消息通知,也就是我要一直在等待銀行辦理業務情況;
第二種:後者(等待別人通知)就是非同步等待消息通知。在非同步消息處理中,等待消息通知者(在這個例子中就是等待辦理業務的人)往往註冊一個回調機制,在所等待的事件被觸發時由觸發機制(在這裡是櫃臺的人)通過某種機制(在這裡是寫在小紙條上的號碼,喊號)找到等待該事件的人。
例子
阻塞與非阻塞
阻塞和非阻塞這兩個概念與程式(線程)等待消息通知(無所謂同步或者非同步)時的狀態有關。也就是說阻塞與非阻塞主要是程式(線程)等待消息通知時的狀態角度來說的
繼續上面的那個例子,不論是排隊還是使用號碼等待通知,如果在這個等待的過程中,等待者除了等待消息通知之外不能做其它的事情,那麼該機制就是阻塞的,表現在程式中,也就是該程式一直阻塞在該函數調用處不能繼續往下執行。
相反,有的人喜歡在銀行辦理這些業務的時候一邊打打電話發發簡訊一邊等待,這樣的狀態就是非阻塞的,因為他(等待者)沒有阻塞在這個消息通知上,而是一邊做自己的事情一邊等待。
註意:同步非阻塞形式實際上是效率低下的,想象一下你一邊打著電話一邊還需要抬頭看到底隊伍排到你了沒有。如果把打電話和觀察排隊的位置看成是程式的兩個操作的話,這個程式需要在這兩種不同的行為之間來回的切換,效率可想而知是低下的;而非同步非阻塞形式卻沒有這樣的問題,因為打電話是你(等待者)的事情,而通知你則是櫃臺(消息觸發機制)的事情,程式沒有在兩種不同的操作中來回切換。
例子
同步/非同步與阻塞/非阻塞
- 同步阻塞形式
效率最低。拿上面的例子來說,就是你專心排隊,什麼別的事都不做。
- 非同步阻塞形式
如果在銀行等待辦理業務的人採用的是非同步的方式去等待消息被觸發(通知)
,也就是領了一張小紙條,假如在這段時間里他不能離開銀行做其它的事情,那麼很顯然,這個人被阻塞在了這個等待的操作上面;
非同步操作是可以被阻塞住的,只不過它不是在處理消息時阻塞,而是在等待消息通知時被阻塞。
- 同步非阻塞形式
實際上是效率低下的。
想象一下你一邊打著電話一邊還需要抬頭看到底隊伍排到你了沒有,如果把打電話和觀察排隊的位置看成是程式的兩個操作的話,這個程式需要在這兩種不同的行為之間來回的切換
,效率可想而知是低下的。
- 非同步非阻塞形式
效率更高,
因為打電話是你(等待者)的事情,而通知你則是櫃臺(消息觸發機制)的事情,程式沒有在兩種不同的操作中來回切換
。
比如說,這個人突然發覺自己煙癮犯了,需要出去抽根煙,於是他告訴大堂經理說,排到我這個號碼的時候麻煩到外面通知我一下,那麼他就沒有被阻塞在這個等待的操作上面,自然這個就是非同步+非阻塞的方式了。
很多人會把同步和阻塞混淆,是因為很多時候同步操作會以阻塞的形式表現出來
,同樣的,很多人也會把非同步和非阻塞混淆,因為非同步操作一般都不會在真正的IO操作處被阻塞
。
進程的創建與結束
進程的創建
但凡是硬體,都需要有操作系統去管理,只要有操作系統,就有進程的概念,就需要有創建進程的方式,一些操作系統只為一個應用程式設計,比如微波爐中的控制器,一旦啟動微波爐,所有的進程都已經存在。
而對於通用系統(跑很多應用程式),需要有系統運行過程中創建或撤銷進程的能力,主要分為4中形式創建新的進程:
1. 系統初始化(查看進程linux中用ps命令,windows中用任務管理器,前臺進程負責與用戶交互,後臺運行的進程與用戶無關,運行在後臺並且只在需要時才喚醒的進程,稱為守護進程,如電子郵件、web頁面、新聞、列印)
2. 一個進程在運行過程中開啟了子進程(如nginx開啟多進程,os.fork,subprocess.Popen等)
3. 用戶的互動式請求,而創建一個新進程(如用戶雙擊暴風影音)
4. 一個批處理作業的初始化(只在大型機的批處理系統中應用)
無論哪一種,新進程的創建都是由一個已經存在的進程執行了一個用於創建進程的系統調用而創建的。
1. 在UNIX中該系統調用是:fork,fork會創建一個與父進程一模一樣的副本,二者有相同的存儲映像、同樣的環境字元串和同樣的打開文件(在shell解釋器進程中,執行一個命令就會創建一個子進程) 2. 在windows中該系統調用是:CreateProcess,CreateProcess既處理進程的創建,也負責把正確的程式裝入新進程。 關於創建子進程,UNIX和windows 1.相同的是:進程創建後,父進程和子進程有各自不同的地址空間(多道技術要求物理層面實現進程之間記憶體的隔離),任何一個進程的在其地址空間中的修改都不會影響到另外一個進程。 2.不同的是:在UNIX中,子進程的初始地址空間是父進程的一個副本,提示:子進程和父進程是可以有隻讀的共用記憶體區的。但是對於windows系統來說,從一開始父進程與子進程的地址空間就是不同的。創建進程
進程的結束
1. 正常退出(自願,如用戶點擊互動式頁面的叉號,或程式執行完畢調用發起系統調用正常退出,在linux中用exit,在windows中用ExitProcess)
2. 出錯退出(自願,python a.py中a.py不存在)
3. 嚴重錯誤(非自願,執行非法指令,如引用不存在的記憶體,1/0等,可以捕捉異常,try...except...)
4. 被其他進程殺死(非自願,如kill -9)
在python程式中的進程操作
之前我們已經瞭解了很多進程相關的理論知識,瞭解進程是什麼應該不再困難了,剛剛我們已經瞭解了,運行中的程式就是一個進程。所有的進程都是通過它的父進程來創建的。因此,運行起來的python程式也是一個進程,那麼我們也可以在程式中再創建進程。多個進程可以實現併發效果,也就是說,當我們的程式中存在多個進程的時候,在某些時候,就會讓程式的執行速度變快。以我們之前所學的知識,並不能實現創建進程這個功能,所以我們就需要藉助python中強大的模塊。
multiprocess模塊
仔細說來,multiprocess不是一個模塊而是python中一個操作、管理進程的包。 之所以叫multi是取自multiple的多功能的意思,在這個包中幾乎包含了和進程有關的所有子模塊。由於提供的子模塊非常多,為了方便大家歸類記憶,我將這部分大致分為四個部分:創建進程部分,進程同步部分,進程池部分,進程之間數據共用。
multiprocess.process模塊
process模塊介紹
process模塊是一個創建進程的模塊,藉助這個模塊,就可以完成進程的創建。
Process([group [, target [, name [, args [, kwargs]]]]]),由該類實例化得到的對象,表示一個子進程中的任務(尚未啟動) 強調: 1. 需要使用關鍵字的方式來指定參數 2. args指定的為傳給target函數的位置參數,是一個元組形式,必須有逗號 參數介紹: 1 group參數未使用,值始終為None 2 target表示調用對象,即子進程要執行的任務 3 args表示調用對象的位置參數元組,args=(1,2,'egon',) 4 kwargs表示調用對象的字典,kwargs={'name':'egon','age':18} 5 name為子進程的名稱
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開啟的進程方法介紹
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字元的字元串。這個鍵的用途是為涉及網路連接的底層進程間通信提供安全性,這類連接只有在具有相同的身份驗證鍵時才能成功(瞭解即可)屬性介紹
在Windows操作系統中由於沒有fork(linux操作系統中創建進程的機制),在創建子進程的時候會自動 import 啟動它的這個文件,而在 import 的時候又執行了整個文件。因此如果將process()直接寫在文件中就會無限遞歸創建子進程報錯。所以必須把創建子進程的部分使用if __name__ ==‘__main__’ 判斷保護起來,import 的時候 ,就不會遞歸運行了。在windows中使用process模塊的註意事項
使用process模塊創建進程
在一個python進程中開啟子進程,start方法和併發效果。
import time from multiprocessing import Process def f(name): print('hello', name) print('我是子進程') if __name__ == '__main__': p = Process(target=f, args=('bob',)) p.start() time.sleep(1) print('執行主進程的內容了')在python中啟動的第一個子進程
import time from multiprocessing import Process def f(name): print('hello', name) time.sleep(1) print('我是子進程') if __name__ == '__main__': p = Process(target=f, args=('bob',)) p.start() #p.join() print('我是父進程')join方法
import os from multiprocessing import Process def f(x): print('子進程id :',os.getpid(),'父進程id :',os.getppid()) return x*x if __name__ == '__main__': print('主進程id :', os.getpid()) p_lst = [] for i in range(5): p = Process(target=f, args=(i,)) p.start()查看主進程和子進程的進程號
進階,多個進程同時運行(註意,子進程的執行順序不是根據啟動順序決定的)
import time from multiprocessing import Process def f(name): print('hello', name) time.sleep(1) if __name__ == '__main__': p_lst = [] for i in range(5): p = Process(target=f, args=('bob',)) p.start() p_lst.append(p)多個進程同時運行
import time from multiprocessing import Process def f(name): print('hello', name) time.sleep(1) if __name__ == '__main__': p_lst = [] for i in range(5): p = Process(target=f, args=('bob',)) p.start() p_lst.append(p) p.join() # [p.join() for p in p_lst] print('父進程在執行')多個進程同時運行,再談join方法(1)
import time from multiprocessing import Process def f(name): print('hello', name) time.sleep(1) if __name__ == '__main__': p_lst = [] for i in range(5): p = Process(target=f, args=('bob',)) p.start() p_lst.append(p) # [p.join() for p in p_lst] print('父進程在執行')多個進程同時運行,再談join方法(2)
除了上面這些開啟進程的方法,還有一種以繼承Process類的形式開啟進程的方式
import os from multiprocessing import Process class MyProcess(Process): def __init__(self,name): super().__init__() self.name=name def run(self): print(os.getpid()) print('%s 正在和女主播聊天' %self.name) p1=MyProcess('wupeiqi') p2=MyProcess('yuanhao') p3=MyProcess('nezha') p1.start() #start會自動調用run p2.start() # p2.run() p3.start() p1.join() p2.join() p3.join() print('主線程')通過繼承Process類開啟進程
進程之間的數據隔離問題
from multiprocessing import Process def work(): global n n=0 print('子進程內: ',n) if __name__ == '__main__': n = 100 p=Process(target=work) p.start() print('主進程內: ',n)進程之間的數據隔離問題
守護進程
會隨著主進程的結束而結束。
主進程創建守護進程
其一:守護進程會在主進程代碼執行結束後就終止
其二:守護進程內無法再開啟子進程,否則拋出異常:AssertionError: daemonic processes are not allowed to have children
註意:進程之間是互相獨立的,主進程代碼運行結束,守護進程隨即終止
import os import time from multiprocessing import Process class Myprocess(Process): def __init__(self,person): super().__init__() self.person = person def run(self): print(os.getpid(),self.name) print('%s正在和女主播聊天' %self.person) p=Myprocess('哪吒') p.daemon=True #一定要在p.start()前設置,設置p為守護進程,禁止p創建子進程,並且父進程代碼執行結束,p即終止運行 p.start() time.sleep(10) # 在sleep時查看進程id對應的進程ps -ef|grep id print('主')守護進程的啟動
from multiprocessing import Process def foo(): print(123) time.sleep(1) print("end123") def bar(): print(456) time.sleep(3) print("end456") p1=Process(target=foo) p2=Process(target=bar) p1.daemon=True p1.start() p2.start() time.sleep(0.1) print("main-------")#列印該行則主進程代碼結束,則守護進程p1應該被終止.#可能會有p1任務執行的列印信息123,因為主進程列印main----時,p1也執行了,但是隨即被終止.主進程代碼執行結束守護進程立即結束
socket聊天併發實例
from socket import * from multiprocessing import Process server=socket(AF_INET,SOCK_STREAM) server.setsockopt(SOL_SOCKET,SO_REUSEADDR,1) server.bind(('127.0.0.1',8080)) server.listen(5) def talk(conn,client_addr): while True: try: msg=conn.recv(1024) if not msg:break conn.send(msg.upper()) except Exception: break if __name__ == '__main__': #windows下start進程一定要寫到這下麵 while True: conn,client_addr=server.accept() p=Process(target=talk,args=(conn,client_addr)) p.start()使用多進程實現socket聊天併發-server