Cpython的程序,執行緒,協程,io模型
一、程序:
一 基礎概念:
1、程序的定義: 程序本身是一個抽象的概念,程序是作業系統資源分配的基本單位,是正在進行的一個過程或者說一個任務,負責執行任務的是cpu。
2、並行與併發: 假設計算機只有一個cpu,由於一個cpu在同一時間只能執行一個任務,那麼當有多個任務想同時執行按道理那麼需要多個cpu執行
這個時候如果有多個cpu同時執行這些任務就是並行,如果是一個cpu執行多個任務(其實就是cpu在多個任務之間來回切換則為併發)
那麼由此定義如下:
並行:多個任務同時執行,只有具備多個cpu才能實現並行。
併發:偽並行,看起來是同時執行多個任務,實際上是單個CPU在多個程式之間來回切換。
3、同步與非同步: 當一個程序在執行多個任務時,如果要等待到該任務執行完成才會繼續執行下個任務,那麼就屬於同步。
如果該程序在執行某個任務是,不等待該任務是否完成而繼續執行下個任務,那麼就是非同步。
舉個例子:
打電話就是同步,你必須跟這個人通話完成(排除呼叫等待)才能接另外一個人的電話,不能同時接兩個人的電話
發簡訊就是非同步,QQ聊天也是非同步,你可以不用等待收件人是否有回覆資訊而繼續和其他人聊天。
4、阻塞與非阻塞: 阻塞:呼叫結果返回之前,該執行程式會被掛起,不釋放CPU執行權,執行緒不能做其它事情,只能等待,只有等到呼叫結果返回了,才能接著往下執行;
非阻塞:就是在沒有獲取呼叫結果時,不是一直等待,執行緒可以往下執行,如果是同步的,通過輪詢的方式檢查有沒有呼叫結果返回,如果是非同步的,會通知回撥。
5、同步、非同步、阻塞、非阻塞區別:(參考知乎的回答)
同步與非同步關注的是:訊息的通訊機制,阻塞與非阻塞關注的是:程式在等待呼叫結果時的狀態,
舉個例子:
比如你打電話問書店老闆有沒有《gold瓶梅》這本書:
如果是同步通訊機制,老闆說你稍等我查下,(可能等待一天或者幾秒)然後告訴你返回結果。
非同步通訊機制,老闆會直接告訴你我查下,查好了打電話給你,然後直接掛電話(不返回結果),查好了老闆會打電話給你。
阻塞機制:你會把自己一直掛起,等待老闆給你打電話告知這本書的查詢結果,知道有返回結果。
非阻塞機制:你不管老闆有沒有告訴你,你自己先一邊去幹別的了,然後根據你自己設定的時間檢查老闆有沒有返回結果給你。
二 程序的建立和終止:
建立:
1. 系統初始化(檢視程序linux中用ps命令,windows中用工作管理員)
2. 一個程序在執行過程中開啟了子程序
3. 使用者的互動式請求,而建立一個新程序(如使用者雙擊暴風影音)
終止:
1. 正常退出
2. 出錯退出
3. 被其他程序殺死
三 程序間的通訊方式:
1、管道:管道可用於具有親緣關係的父子程序間的通訊
2、訊號:用於通知程序有某事件發生,一個程序收到一個訊號與處理器收到一箇中斷請求效果上可以說是一致的。
3、訊息佇列:訊息佇列是訊息的連結表。
4、共享記憶體:使得多個程序可以訪問同一塊記憶體空間,不同程序可以及時看到對方程序中對共享記憶體中資料得更新。
5、訊號量:主要作為程序之間及同一種程序的不同執行緒之間得同步和互斥手段。
6、套接字:它可用於網路中不同機器之間的程序間通訊。
二、執行緒:
一基礎概念:
1、執行緒的定義:執行緒是程序中執行運算的最小單位,是程序中的一個實體,是被系統獨立排程和分派的基本單位多執行緒是,在一個程序中存在多個控制執行緒,多個控制執行緒共享該程序的地址空間。
2、執行緒的特點:
-
-
首先易於排程。其次提高併發性。通過執行緒可方便有效地實現併發性。程序可建立多個執行緒來執行同一程式的不同部分。還有就是開銷少。
-
二程序與執行緒的關係以及區別:
關係:
-
-
一個執行緒只能屬於一個程序,而一個程序可以有多個執行緒,但至少有一個執行緒。
-
同一程序的所有執行緒共享該程序的所有資源。
-
執行緒在執行過程中,需要協作同步。
-
區別:
-
-
排程:執行緒作為排程和分配的基本單位,程序作為擁有資源的基本單位
-
併發性:不僅程序之間可以併發執行,同一個程序的多個執行緒之間也可併發執行
-
擁有資源:程序是擁有資源的一個獨立單位,執行緒不擁有系統資源,但可以訪問隸屬於程序的資源.
-
系統開銷:在建立或撤消程序時,由於系統都要為之分配和回收資源,導致系統的開銷明顯大於建立或撤消執行緒時的開銷。
-
三、協程:
一基礎概念:
1、協程的定義:協程是一種使用者態的輕量級執行緒,即協程是由使用者程式自己控制排程的
二協程的特點:
1、協程的切換開銷更小,屬於程式級別的切換,作業系統完全感知不到,因而更加輕量級
2、必須在只有一個單執行緒裡實現併發
3、修改共享資料不需加鎖
四、IO模型:
由於程序是不可直接訪問外部裝置的,所以只能呼叫核心去呼叫外部的裝置(上下文切換),然後外部裝置比如磁碟,讀出儲存在裝置自身的資料傳送給核心緩衝區,核心緩衝區在copy資料到使用者程序的緩衝區。在外部裝置響應的給到使用者程序過程中,包含了兩個階段;由於資料響應方式的不同,所以就有了不同的I/O模型。
IO模型的區別主要在以下兩個階段上:
1)等待資料準備。
2)將資料從核心拷貝到程序中。
一、阻塞IO:
如下
當用戶呼叫了recvfrom程序,核心第一個階段:準備資料。網路 io來說,很多時候資料在一開始還沒有到達,這個時候核心就要等待足夠的資料到來。
而在使用者程序這邊,整個程序會被阻塞。當核心收到資料,它就會將資料拷貝到使用者記憶體,使用者程序才解除block的狀態,重新執行起來。
二、非阻塞IO:
如下:
非阻塞的recvform系統呼叫呼叫之後,程序並沒有被阻塞,核心馬上返回給程序,如果資料還沒準備好,此時會返回一個error。程序在返回之後,可以乾點別的事情,然後再發起recvform系統呼叫。重複上面的過程,迴圈往復的進行recvform系統呼叫。這個過程通常被稱之為輪詢。輪詢檢查核心資料,直到資料準備好,再拷貝資料到程序,進行資料處理。需要注意,拷貝資料整個過程,程序仍然是屬於阻塞的狀態,在非阻塞式IO中,使用者程序其實是需要不斷的主動詢問kernel資料準備好了沒有。相當於上面的例子你自己設定個時間輪詢詢問老闆有沒有找到你要的書
三、多路複用IO:
有些地方也稱這種IO方式為事件驅動IO(event driven IO),
在核心請求IO裝置響應指令發出後,資料就開始準備,在此期間使用者程序是阻塞的。資料從kernel buffer複製到使用者程序的過程也是阻塞的。但是和阻塞I/O所不同的是,它可以同時阻塞多個I/O操作,而且可以同時對多個讀操作,多個寫操作的I/O函式進行檢測,直到有資料可讀或可寫時,才真正呼叫I/O操作函式,也就是說一個執行緒可以響應多個請求。
四、非同步IO:
使用者程序發起read操作之後,立刻就可以開始去做其它的事。從核心的角度,當它受到一個asynchronous read之後,首先它會立刻返回,所以不會對使用者程序產生任何block。然後,kernel會等待資料準備完成,然後將資料拷貝到使用者記憶體,當這一切都完成之後,kernel會給使用者程序傳送一個signal,告訴它read操作完成了。
五、IO模型對比:
non-blocking IO和asynchronous IO的區別還是很明顯的。在non-blocking IO中,雖然程序大部分時間都不會被block,但是它仍然要求程序去主動的check,並且當資料準備完成以後,也需要程序主動的再次呼叫recvfrom來將資料拷貝到使用者記憶體。而asynchronous IO則完全不同。它就像是使用者程序將整個IO操作交給了他人(kernel)完成,然後他人做完後發訊號通知。在此期間,使用者程序不需要去檢查IO操作的狀態,也不需要主動的去拷貝資料。
參考部落格:https://www.cnblogs.com/microfan/p/5294250.html
https://blog.csdn.net/linhuaiyang/article/details/68483222