事件驅動模型
"""問題:遇到io操作就切換
但是,什麼時候切回去了?怎麼確定io操作完了呢?
傳統的程式設計是如下線性模式的:
開始-->**塊a-->**塊b-->**塊c-->**塊d-->..結束
每乙個**塊裡是完成各種各樣事情的**.但程式設計者需要知道**塊a,b,c,d的執行順序.唯一能夠改變這個流程的資料.輸入不同的資料,根據條件語句判斷.流程或許就改為a-->c-->e..-->結束.每一次程式執行順序或許很不同,但它的控制流程是由輸入資料和你編寫的程式決定的.如果你知道這個程式當前的執行狀態(包括輸入資料和程式本身),那你就知道接下來甚至一直到它結束的執行流程.
對於事件驅動型程式模型,它的流程大致如下:
開始->初始化-->等等
與上面傳統的模式不同,事件驅動程式在啟動之後,就在那裡等待,等待什麼呢?等待事件被觸發.傳統程式設計下也有'等待'的時候,比如你在**塊d中,你定義了乙個input(),需要使用者輸入資料.但這與下面的等待不同,傳統程式設計的"等待",比如"input()",你作為程式編寫者是知道或者強制使用者輸入某個東西的,或許是數字,或許是檔名稱,如果使用者輸入錯誤,你還需要提醒他,並請他重新輸入.事件驅動程式的等待則是完全不知道,也不強制使用者輸入或者幹什麼.只要某一事件發生,那麼程式就會做出相應的"反應",這些事件包括:輸入資訊,滑鼠,敲擊鍵盤上的某個鍵還有系統內部定時器觸發.
ui程式設計都是這種思想.以後工作的時候也基本是這種思想.
事件驅動程式設計思想:一種程式設計正規化.就是一種寫**的思路
"""# while true:
# # 檢測click什麼時候發生.
# pass # 死迴圈的時候就是把cpu一直占用.極大的浪費cpu
"""建立乙個執行緒迴圈檢測是否有滑鼠點選:
那麼這個方式有以下幾個缺點:
1.>cpu資源浪費,可能滑鼠點選的頻率非常小,但是掃瞄線程還是會一直迴圈檢測,這會造成很多cpu資源浪費,如果掃瞄滑鼠點選的介面是阻塞的呢?
2.>如果是阻塞的,又會出現下面這樣的問題,如果我們不但要掃瞄滑鼠點選,還要掃瞄鍵盤是否按下,由於掃瞄滑鼠時滑鼠被阻塞了,那麼可能永遠不會去掃瞄鍵盤
3.>如果乙個迴圈需要掃瞄的裝置非常多,這又會引來響應時間的問題
所以,該方式是非常不好的.
"""# -------------------------事件驅動模型--------------->
"""目前大部分的ui程式設計都是事件驅動模型,如很多ui平台都會提供onclick()事件,這個事件就代表滑鼠按下事件.事件驅動模型思路如下:
1.>有乙個事件《訊息》佇列
2.>滑鼠按下時,往這個佇列中增加乙個點選事件《訊息》
3.>有個迴圈,不斷從佇列取出事件,根據不同的事件,呼叫不同的函式,如onclick(),
onkeydown()等
4.>事件《訊息》一般都各自儲存各自的處理函式指標,這樣,每個訊息都有獨立的處理函式.
事件佇列:放事件的佇列
事件驅動程式設計是一種程式設計正規化,這裡程式的執行是由外部事件來決定.它的特點是包含乙個事件迴圈,當外部事件發生時使用**機制來觸發相應的處理.
另外兩種常見的程式設計正規化是單執行緒同步以及多執行緒程式設計
理解:就是之前專案中使用乙個字典類實現乙個動作對應乙個函式的關係.
誰在監測滑鼠的點選:作業系統
問到誰在和硬體打交道的時候,一定是作業系統.
"""# -----------------------io模型準備-------------------------->
"""協程實現io阻塞自動切換,那麼協程又是怎麼實現的,在原理上如何實現?如何去實現事件驅動的情況下io的自動阻塞的切換,這個專業名詞叫什麼?-->io多路復用
比如socketserver,多個客戶端連線,單執行緒下實現併發效果,就叫多路復用
同步io和非同步io,阻塞io和非阻塞io分別是什麼?到低有什麼區別?不同的人在不同的上下文給出的答案是不同的,所以先限定一下本文的上下文.
本文討論的背景是linux環境下的networkio
""""""
1.>使用者空間和核心空間:
現在作業系統都是採用虛擬儲存器,那麼對32位作業系統而言,它的定址空間為4g<2的32次方》
作業系統的核心是核心,獨立於普通的應用程式,可以訪問受保護的記憶體空間,也有訪問底層硬體裝置的所有許可權.為了保證使用者程序不能直接操作核心,保證核心的安全,作業系統將虛擬空間分為兩部分,一部分為核心空間,一部分為使用者空間.針對linux作業系統而言,將最高的16位元組,供核心使用,稱為核心空間,而將較低的36位元組,供各個程序使用,稱為使用者空間.
2.>程序切換:
為了控制程序的執行,核心必須有能力掛起正在cpu上執行的程序,並恢復以前掛起的某個程序的執行.這種行為被稱為程序切換.這種切換是由作業系統來完成的.因此可以說,任何程序都是在作業系統的核心的支援下執行的,是與核心緊密相關的.
從乙個程序的執行轉到另乙個程序上執行,這個過程中經過下面這些變化:
儲存處理機上下文,包括程式計數器和其他暫存器.
更新pcb資訊
把程序的pcb移入相應的佇列,如就緒,在某事件阻塞等佇列
選擇另乙個程序執行,並更新其pcb
更新記憶體管理的資料結構
恢復處理機上下文
注:切換程序總而言之就是很耗資源的.
3.>程序阻塞:
正在執行的程序,由於期待的某些事件未發生,如請求系統資源失敗,等待某種操作的完成,新資料尚未到達或無新工作做等,則由系統自動執行阻塞原語,使自己由執行狀態變為阻塞狀態,可見,程序的阻塞是程序自身的一種主動行為,也因此只有處於執行態的程序(獲得cpu),才可能將其轉為阻塞狀態.當程序進入阻塞狀態,是不占用cpu資源的.
4.>檔案描述符fd:
檔案描述符是電腦科學中的乙個術語,是乙個用於表述指向檔案的引用的抽象化概念.
檔案描述符在形式上是乙個非負整數.實際上,它是乙個索引值,指向核心為每乙個程序所維護的該程序的開啟檔案的記錄表.當程式開啟乙個現有檔案或則建立乙個新檔案時,核心向程序返回乙個檔案描述符.在程式設計中,一些涉及底層的程式編寫往往會圍繞著檔案描述符展開,但是檔案描述符這一概念往往只適用於unix,linux這樣的作業系統.
5.>快取i/o:
快取i/o又被稱作標準i/o,大多數檔案系統的預設i/o操作都是快取i/o.在linux的快取i/o機制中,作業系統會將i/o的資料快取在檔案的頁快取中,也就是說,資料會先被拷貝到作業系統核心的快取區中,然後才會從作業系統核心的快取區拷貝到應用程式的位址空間.使用者空間沒法直接訪問核心空間.核心態到使用者態的資料拷貝
思考:為啥資料一定要先到核心區,直接到使用者記憶體不是更直接嗎?
答:資料在傳輸過程中需要在應用程式位址空間和核心進行多次資料拷貝操作,這些資料拷貝操作所帶來的cpu以及記憶體開銷是非常大的.
6.>同步io和非同步io,阻塞io和非阻塞io分別是什麼?,到低有什麼區別?這個問題其實不同的人給出的答案都可能不同,比如wiki,就認為非同步io和非阻塞io是乙個東西.這其實是因為不同的人知識背景不同,並且在討論這個問題的時候上下文也不同,所以,本文討論的背景是linux環境下的network io
注意:能夠和硬體發生資料互動的一定是作業系統.
"""# ---------------------快取io-------------------------->
"""1.>阻塞io:在linux中預設情況下所有的socket都是blocking,乙個典型的讀操作流程大致是這樣:
當使用者程序呼叫了recvfrom這個系統呼叫,核心就開始了io的第乙個階段:準備資料.對於network io 來說,很多時候資料在一開始還沒有到達,比如,還沒有收到乙個udp包,這個時候核心就要等待足夠的資料到來.而在使用者程序這邊,整個程序會被阻塞.當核心一直等到資料準備好了,它就會將資料從核心中拷貝到使用者記憶體,然後核心返回結果,使用者程序才解除block的狀態,重新執行起來.
所以,阻塞io的特點就是在io執行的兩個階段都被block了.
2.>非阻塞io:linux下,可以通過設定socket使其變為non-blockingio
發太多的系統呼叫,資料沒有被及時的處理.資料不及時
3.>io多路復用:
io多路復用,select,epoll .有些地方也稱這種io方式為event driven io.我們都知道,select/epoll 的好處就在於單個process就可以同時處理多個網路連線的io,它的基本原理是select/epoll這個功能會不斷的輪詢所負責的所有socket,當某個socket有資料到達了,就通知使用者程序.
當使用者程序呼叫了select,那麼整個程序會被block,核心會監視所有select所負責的socket,當任何乙個socket中的資料準備好了,select就會返回.這個時候使用者程序再呼叫read操作.將資料從核心拷貝到使用者程序.
select 就是乙個函式 在使用者看來 看是否有人連線.如果沒有,一直監聽
recvfrom 又一次系統呼叫
"""
事件驅動模型
事件代表過去發生的事件,事件既是技術架構概念,也是業務概念。以事件為驅動的程式設計模型稱為事件驅動架構eda。eda是一種以事件為媒介,實現元件或服務之間最大松耦合的方式。傳統面向介面程式設計是以介面為媒介,實現呼叫介面者和介面實現者之間的解耦,但是這種解耦程度不是很高,如果介面發生變化,雙方 都需...
python 事件驅動程式設計模型
event input button和text box keyboard key down和key up mouse click 和 drag timer event queue 所有的event都按照發生的先後順序存在event queue裡,先發生的event,就先執行對應的event hand...
Spring的事件驅動模型
spring事件驅動模型的三個概念 事件,事件監聽者 事件發布者。自定義事件 private string name public publishevent object source override public string tostring 自定義時間監聽者 得到event的集合 遍歷集合執...