LVGL是嵌入式設備中常用的圖形顯示庫, 這篇基於 256K Flash 的 AIR32F103CCT6 和 SPI介面的 ST7735 128x160 LCD屏, 介紹 LVGL 在無系統環境和FreeRTO環境, 帶DMA和不帶DMA方式的集成步驟 ...
進程間為什麼需要數據通信?
- 數據傳輸:一個進程需要將它的數據傳送給另外一個進程。
- 資源共用:多個進程之間共用相同的資源。
- 通知事件:一個進程需要向另外一組進程發送消息,通知它們發生了某種事件。
- 進程式控制制:有些進程需要完全控制另一個進程的執行,該控制進程希望能夠攔截另外一個進程的所有操作,並且能夠及時知道它的狀態改變。
主要有管道、消息隊列、共用記憶體、信號量、信號、Socket等六種方式。
管道
管道的本質是內核中的一個緩存,當記憶體創建一個管道後,Linux會返回兩個文件描述符號,一個是寫入端的描述符,一個是輸出端的描述符,可以通過這兩個描述符往管道里寫入或者讀取數據。如果想要實現兩個進程通過管道來通信,則需要讓創建管道的進程fork子進程,這樣子進程就擁有了父進程的文件描述符,這樣子進程之間可以對同一管道的操作。管道這種進程通信方式雖然使用簡單,但是效率比較低,不適合進程間頻繁地交換數據,並且管道只能傳輸無格式的位元組流。
消息隊列
消息隊列的本質就是存放在記憶體中的消息鏈表,而消息本質上是用戶自定義的數據結構。如果進程在消息隊列種讀取了某個消息,這個消息就會被從消息隊列種刪除。
- 消息隊列允許一個或者多個進程向他寫入或者讀取數據。
- 消息隊列可以不遵循FIFO,進行消息隨機查詢。
- 消息隊列的生命周期與內核相同。
- 消息隊列對於交換較少數量的數據很有用,因為無需避免衝突。因為用戶進程往消息隊列種讀寫數據,需要進行系統調用。如果數據量大會造成頻繁的系統調用,因此需要更多的時間以便於內核介入。
共用記憶體
共用記憶體就是允許不相干的進程將同一段物理記憶體連接到它們各自的地址空間中,使得這些記憶體可以訪問同一個物理空間,這個物理記憶體就成為共用記憶體。
- 兩個不同進程的邏輯地址通過頁表映射到物理空間的同一區域,它們所共同指向的這塊區域就是共用記憶體。
- 消息隊列無需避免衝突,而共用記憶體機制可能會發生衝突。
信號量
在多道批處理系統中,多個進程是可以併發執行的,但由於系統的資源有限,進程的執行不是一貫到底的, 而是走走停停,以不可預知的速度向前推進(非同步性)。但有時候我們又希望多個進程能密切合作,按照某個特定的順序依次執行,以實現一個共同的任務。
為瞭解決上述這兩個問題,保證共用記憶體在任何時刻只有一個進程在訪問(互斥),並且使得進程們能夠按照某個特定順序訪問共用記憶體(同步),我們就可以使用進程的同步與互斥機制,常見的比如信號量與 PV 操作。進程的同步與互斥其實是一種對進程通信的保護機制,並不是用來傳輸進程之間真正通信的內容的,但是由於它們會傳輸信號量,所以也被納入進程通信的範疇,稱為低級通信。
- 信號量:信號量其實就是一個變數 ,我們可以用一個信號量來表示系統中某種資源的數量。例如系統連接的印表機資源的數量,可以設置一個初值為1的信號量。
- 原語:操作系統提供的一對原語來對信號量進行操作。
- P操作:
信號量--
,表示申請占用一個資源。如果申請結果小於0,則無資源可用,P操作的進程被阻塞。 - V操作:
信號量++
,表示釋放一個資源。如果信號量+1<0
,表明有進程處於阻塞中等待資源,因此可以喚醒一個等待中的進程,使其運行下去。 - 可以這麼理解,當信號量的值為 2 的時候,表示有 2 個資源可以使用,當信號量的值為 -2 的時候,表示有兩個進程正在等待使用這個資源。
- P操作:
信號
通過發送指定信號來通知某個非同步事件的發送,以迫使進程進行信號處理程式。信號處理完畢後,被中斷的進程將恢復執行。
- 信號和信號量是完全不同的概念。
- 信號是進程通信機制中唯一的非同步通信機制,它可以在任何時候發送信號給某個進程。
- 信號事件的來源主要有硬體來源和軟體來源。
- 硬體來源,例如組合鍵Ctrl+C 產生 SIGINT 信號,表示終止該進程。
- 軟體來源,通過 kill 系列的命令給進程發送信號,比如 kill -9 1111,給PID 1111進程發送SIGKILL信號。
Socket
通過Socket相關協議,一臺電腦可以接收其他電腦的數據,也可以向其他電腦發送數據,當然也能完成同主機上的進程通信。
- Socket本質上是一個API,是應用層與TCP/IP協議的中間軟體抽象層,對TCP/IP進行了封裝。