進(jìn)程間為何要通訊 ?
鴻蒙內(nèi)核默認(rèn)支持 64個進(jìn)程和128個任務(wù),由進(jìn)程池和任務(wù)池統(tǒng)一管理.內(nèi)核設(shè)計盡量不去打擾它們,讓各自過好各自的日子, 但大家畢竟在一口鍋里吃飯, 不可能不與外界聯(lián)系, 聯(lián)系就得有渠道,有規(guī)矩.
舉兩個應(yīng)用場景說明下通訊的必要性:
一.被動式廣為熟知的shell命令 kill 9 13 ,是通過 shell任務(wù)給 13號進(jìn)程發(fā)送一個干掉它的信號.
#define SIGKILL 9 //常用的命令 kill 9 13
這是被動式通訊的場景,至于為什么要干掉你,原因可能很多啊,很可能是檢測到13占用內(nèi)存太多了,也可能13太低調(diào)長期不活躍,啟動新進(jìn)程發(fā)現(xiàn)沒位置了,得先收了你.總之系統(tǒng)必須得有對付你的抓手,可以隨時登門查水電表.
二.主動式的,比如要訪問某些公共資源(全局變量,消息隊列),而資源有限或具有排他性,別人正在使用導(dǎo)致你不能用, 所以需統(tǒng)一管理,要用就必須要先申請,按規(guī)矩辦事,畢竟和諧社會沒規(guī)矩不成方圓.如果申請失敗了就需要排隊了,同時還要讓出CPU給別人占用了,否則占著茅坑不辦事這樣對大家都不好撒.
大致有以下幾種通訊需求:
(1).數(shù)據(jù)傳輸:一個進(jìn)程需要將它的數(shù)據(jù)發(fā)送給另一個進(jìn)程,發(fā)送的數(shù)據(jù)量在一個字節(jié)到KB字節(jié)之間.(liteipc消息隊列默認(rèn)1K)
(2).共享數(shù)據(jù):多個進(jìn)程想要操作共享數(shù)據(jù),一個進(jìn)程對共享數(shù)據(jù)的修改,別的進(jìn)程應(yīng)該立刻看到。
(3).通知事件:一個進(jìn)程需要向另一個或一組進(jìn)程發(fā)送消息,通知它(它們)發(fā)生了某種事件(如進(jìn)程終止時要通知父進(jìn)程)。
(4).資源共享:多個進(jìn)程之間共享同樣的資源。為了做到這一點,需要內(nèi)核提供鎖和同步機制。
(5).進(jìn)程控制:有些進(jìn)程希望完全控制另一個進(jìn)程的執(zhí)行(如Debug進(jìn)程),此時控制進(jìn)程希望能夠攔截另一個進(jìn)程的所有陷入和異常,并能夠及時知道它的狀態(tài)改變。
內(nèi)核目錄和系列篇更新
內(nèi)核有個專門的IPC目錄,詳見如下. 可直接點擊查看注解源碼.
進(jìn)程間九種通訊方式
1.管道pipe(fs_syscall.c)
管道是一種最基本的IPC機制,作用于有血緣關(guān)系的進(jìn)程之間,完成數(shù)據(jù)傳遞。 調(diào)用pipe系統(tǒng)函數(shù)即可創(chuàng)建一個管道。有如下特質(zhì):
其本質(zhì)是一個偽文件(實為內(nèi)核緩沖區(qū))
由兩個文件描述符引用,一個表示讀端,一個表示寫端。
規(guī)定數(shù)據(jù)從管道的寫端流入管道,從讀端流出。
管道的原理: 管道實為內(nèi)核使用環(huán)形隊列機制,借助內(nèi)核緩沖區(qū)(4k)實現(xiàn)。 管道的局限性: ① 數(shù)據(jù)自己讀不能自己寫。 ② 數(shù)據(jù)一旦被讀走,便不在管道中存在,不可反復(fù)讀取。 ③ 由于管道采用半雙工通信方式。因此,數(shù)據(jù)只能在一個方向上流動。 ④ 只能在有公共祖先的進(jìn)程間使用管道。 常見的通信方式有,單工通信、半雙工通信、全雙工通信。
這部分后系列篇文件相關(guān)篇中會重點講,敬請關(guān)注. 詳細(xì)看SysPipe函數(shù).
2.信號(los_signal.c)
信號思想來自Unix,在發(fā)展了50年之后,許多方面都沒有發(fā)生太大的變化.信號可以由內(nèi)核產(chǎn)生,也可以由用戶進(jìn)程產(chǎn)生,并由內(nèi)核傳送給特定的進(jìn)程或線程(組),若這個進(jìn)程注冊/安裝了自己的信號處理程序,則內(nèi)核會調(diào)用這個函數(shù)去處理信號,否則則執(zhí)行默認(rèn)的函數(shù)或者忽略.信號分為兩大類:可靠信號與不可靠信號,前32種信號為不可靠信號,后32種為可靠信號。長這樣:
#define SIGHUP 1 //終端掛起或者控制進(jìn)程終止 #define SIGINT 2 //鍵盤中斷(如break鍵被按下) #define SIGQUIT 3 //鍵盤的退出鍵被按下 #define SIGILL 4 //非法指令 #define SIGTRAP 5 //跟蹤陷阱(trace trap),啟動進(jìn)程,跟蹤代碼的執(zhí)行 #define SIGABRT 6 //由abort(3)發(fā)出的退出指令 #define SIGIOT SIGABRT #define SIGBUS 7 //總線錯誤 #define SIGFPE 8 //浮點異常 #define SIGKILL 9 //常用的命令 kill 9 13 #define SIGUSR1 10 //用戶自定義信號1
信號為系統(tǒng)提供了一種進(jìn)程間異步通訊的方式,一個進(jìn)程不必通過任何操作來等待信號的到達(dá)。事實上,進(jìn)程也不可能知道信號到底什么時候到達(dá)。一般來說,只需用戶進(jìn)程提供信號處理函數(shù),內(nèi)核會想方設(shè)法調(diào)用信號處理函數(shù),處理過程如圖所示:
個人把這種異步通訊過程理解為生產(chǎn)者(安裝和發(fā)送信號)和消費者(捕捉和處理信號)兩個部分,分姊妹兩篇已完成
v48.xx (信號生產(chǎn)篇) | 如何安裝和發(fā)送信號?
v49.xx (信號消費篇) | 用戶棧到內(nèi)核棧的兩次切換
3.消息隊列(los_queue.c)
基本概念
隊列又稱消息隊列,是一種常用于任務(wù)間通信的數(shù)據(jù)結(jié)構(gòu)。隊列接收來自任務(wù)或中斷的 不固定長度消息,并根據(jù)不同的接口確定傳遞的消息是否存放在隊列空間中。
任務(wù)能夠從隊列里面讀取消息,當(dāng)隊列中的消息為空時,掛起讀取任務(wù);當(dāng)隊列中有新消息時, 掛起的讀取任務(wù)被喚醒并處理新消息。任務(wù)也能夠往隊列里寫入消息,當(dāng)隊列已經(jīng)寫滿消息時, 掛起寫入任務(wù);當(dāng)隊列中有空閑消息節(jié)點時,掛起的寫入任務(wù)被喚醒并寫入消息。如果將 讀隊列和寫隊列的超時時間設(shè)置為0,則不會掛起任務(wù),接口會直接返回,這就是非阻塞模式。
消息隊列提供了異步處理機制,允許將一個消息放入隊列,但不立即處理。同時隊列還有緩沖消息的作用。
隊列特性
消息以先進(jìn)先出的方式排隊,支持異步讀寫。 讀隊列和寫隊列都支持超時機制。 每讀取一條消息,就會將該消息節(jié)點設(shè)置為空閑。 發(fā)送消息類型由通信雙方約定,可以允許不同長度(不超過隊列的消息節(jié)點大?。┑南?。 一個任務(wù)能夠從任意一個消息隊列接收和發(fā)送消息。 多個任務(wù)能夠從同一個消息隊列接收和發(fā)送消息。 創(chuàng)建隊列時所需的隊列空間,默認(rèn)支持接口內(nèi)系統(tǒng)自行動態(tài)申請內(nèi)存的方式,同時也支持將用戶分配的隊列空間作為接口入?yún)魅氲姆绞健?/p>
詳細(xì)可前往查看:
v33.xx (消息隊列篇) | 進(jìn)程間如何異步解耦傳遞大數(shù)據(jù) ?
4.共享內(nèi)存(shm.c)
共享內(nèi)存是進(jìn)程間通信中最簡單的方式之一。共享內(nèi)存允許兩個或更多進(jìn)程訪問同一塊物理內(nèi)存,每個進(jìn)程都要單獨對這塊物理內(nèi)存進(jìn)行映射.當(dāng)一個進(jìn)程改變了這塊地址中的內(nèi)容的時候,該物理頁框?qū)⒈粯?biāo)記為臟頁,如此其它進(jìn)程都會知道內(nèi)容發(fā)生了更改。
這部分后系列篇內(nèi)存相關(guān)篇中會重點講,內(nèi)存部分雖已寫過幾篇,但是沒講透,要重新再梳理.
5.信號量(los_sem.c)
基本概念
信號量(Semaphore)是一種實現(xiàn)任務(wù)間通信的機制,可以實現(xiàn)任務(wù)間同步或共享資源的互斥訪問。 一個信號量的數(shù)據(jù)結(jié)構(gòu)中,通常有一個計數(shù)值,用于對有效資源數(shù)的計數(shù),表示剩下的可被使用的共享資源數(shù)。
對信號量有個形象的比喻 停車場的停車位, 進(jìn)停車場前看下屏幕上實時顯示剩余車位,0表示不能進(jìn),只有大于0才能進(jìn)入,進(jìn)入后自動減1,出口處也加了監(jiān)測,出去后剩余車位增加1個.
使用場景
在多任務(wù)系統(tǒng)中,信號量是一種非常靈活的同步方式,可以運用在多種場合中,實現(xiàn)鎖、同步、資源計數(shù)等功能, 也能方便的用于任務(wù)與任務(wù),中斷與任務(wù)的同步中。常用于協(xié)助一組相互競爭的任務(wù)訪問共享資源。
詳細(xì)可前往查看:
v29.xx (信號量篇) | 信號量解決任務(wù)同步問題
6.互斥鎖 (los_mux.c) :
基本概念
互斥鎖又稱互斥型信號量,是一種特殊的二值性信號量,用于實現(xiàn)對臨界資源的獨占式處理。 另外,互斥鎖可以解決信號量存在的優(yōu)先級翻轉(zhuǎn)問題。 任意時刻互斥鎖只有兩種狀態(tài),開鎖或閉鎖。當(dāng)任務(wù)持有時,這個任務(wù)獲得該互斥鎖的所有權(quán), 互斥鎖處于閉鎖狀態(tài)。當(dāng)該任務(wù)釋放鎖后,任務(wù)失去該互斥鎖的所有權(quán),互斥鎖處于開鎖狀態(tài)。 當(dāng)一個任務(wù)持有互斥鎖時,其他任務(wù)不能再對該互斥鎖進(jìn)行開鎖或持有。
詳細(xì)可前往查看:
v27.xx (互斥鎖篇) | 互斥鎖比自旋鎖可豐滿許多
v26.xx (自旋鎖篇) | 真的好想為自旋鎖立貞節(jié)牌坊!
7.快鎖 (los_futex.c)
futex 是Fast Userspace muTexes的縮寫(快速用戶空間互斥體),是一種用戶態(tài)和內(nèi)核態(tài)混合的同步機制。首先,同步的進(jìn)程間通過mmap共享一段內(nèi)存,futex變量就位于這段共享的內(nèi)存中且操作是原子的,當(dāng)進(jìn)程嘗試進(jìn)入互斥區(qū)或者退出互斥區(qū)的時候,先去查看共享內(nèi)存中的futex變量,如果沒有競爭發(fā)生,則只修改futex,而不用再執(zhí)行系統(tǒng)調(diào)用了。當(dāng)通過訪問futex變量告訴進(jìn)程有競爭發(fā)生,則還是得執(zhí)行系統(tǒng)調(diào)用去完成相應(yīng)的處理(wait 或者 wake up)。
注解版同步到官方最新源碼后,發(fā)現(xiàn)快鎖的部分改動很大,這部分要重新注解,敬請留意.
8.事件 (los_event.c)
基本概念事件(Event)是一種任務(wù)間通信的機制,可用于任務(wù)間的同步。
多任務(wù)環(huán)境下,任務(wù)之間往往需要同步操作,一個等待即是一個同步。事件可以提供一對多、多對多的同步操作。 一對多同步模型:一個任務(wù)等待多個事件的觸發(fā)。可以是任意一個事件發(fā)生時喚醒任務(wù)處理事件,也可以是幾個事件都發(fā)生后才喚醒任務(wù)處理事件。 多對多同步模型:多個任務(wù)等待多個事件的觸發(fā)。
事件特點
任務(wù)通過創(chuàng)建事件控制塊來觸發(fā)事件或等待事件。 事件間相互獨立,內(nèi)部實現(xiàn)為一個32位無符號整型,每一位標(biāo)識一種事件類型。第25位不可用,因此最多可支持31種事件類型。 事件僅用于任務(wù)間的同步,不提供數(shù)據(jù)傳輸功能。 多次向事件控制塊寫入同一事件類型,在被清零前等效于只寫入一次。 多個任務(wù)可以對同一事件進(jìn)行讀寫操作。 支持事件讀寫超時機制。
事件可應(yīng)用于多種任務(wù)同步場景,在某些同步場景下可替代信號量。
使用場景
隊列用于任務(wù)間通信,可以實現(xiàn)消息的異步處理。同時消息的發(fā)送方和接收方不需要彼此聯(lián)系,兩者間是解耦的。
詳細(xì)可前往查看:
v30.xx (事件控制篇) | 任務(wù)間多對多的同步方案
9.文件消息隊列 (hm_liteipc.c)
基于文件實現(xiàn)的消息隊列,特點是隊列中消息數(shù)量多(256個),傳遞消息內(nèi)容大(可到1K)
#define IPC_MSG_DATA_SZ_MAX 1024 //最大的消息內(nèi)容 1K ,posix最大消息內(nèi)容 64個字節(jié) #define IPC_MSG_OBJECT_NUM_MAX 256 //最大的消息數(shù)量256 ,posix最大消息數(shù)量 16個
文件消息隊列隱約感覺鴻蒙的分布式通訊,跨屏之類的功能是靠它實現(xiàn)的,分布式的代碼還沒研究,尚不清楚,如果有了解的請告知.后續(xù)要重點研究下跨應(yīng)用通訊的技術(shù)實現(xiàn).
編輯:hfy
-
進(jìn)程
+關(guān)注
關(guān)注
0文章
203瀏覽量
13961 -
鴻蒙系統(tǒng)
+關(guān)注
關(guān)注
183文章
2634瀏覽量
66344
發(fā)布評論請先 登錄
相關(guān)推薦
評論