1. 程式人生 > >Linux 學習筆記—程序通訊之 訊息佇列、訊號量、共享記憶體的概念區別聯絡

Linux 學習筆記—程序通訊之 訊息佇列、訊號量、共享記憶體的概念區別聯絡

2.5 訊息佇列(Message queues) 訊息佇列是核心地址空間中的內部連結串列,通過linux核心在各個程序直接傳遞內容,訊息順序地傳送到訊息佇列中,並以幾種不同的方式從佇列中獲得,每個訊息佇列可以用IPC識別符號唯一地進行識別。核心中的訊息佇列是通過IPC的識別符號來區別,不同的訊息佇列直接是相互獨立的。每個訊息佇列中的訊息,又構成一個獨立的連結串列。 訊息佇列克服了訊號承載資訊量少,管道只能承載無格式字元流。 訊息佇列的本質 Linux的訊息佇列(queue)實質上是一個連結串列,它有訊息佇列識別符號(queue ID)。 msgget建立一個新佇列或開啟一個存在的佇列;msgsnd向佇列末端新增一條新訊息;msgrcv從佇列中取訊息, 取訊息是不一定遵循先進先出的, 也可以按訊息的型別欄位取訊息。

訊息佇列與命名管道的比較 訊息佇列跟命名管道有不少的相同之處,通過與命名管道一樣,訊息佇列進行通訊的程序可以是不相關的程序,同時它們都是通過傳送和接收的方式來傳遞資料的。在命名管道中,傳送資料用write,接收資料用read,則在訊息佇列中,傳送資料用msgsnd,接收資料用msgrcv。而且它們對每個資料都有一個最大長度的限制。 與命名管道相比,訊息佇列的優勢在於,1、訊息佇列也可以獨立於傳送和接收程序而存在,從而消除了在同步命名管道的開啟和關閉時可能產生的困難。2、同時通過傳送訊息還可以避免命名管道的同步和阻塞問題,不需要由程序自己來提供同步方法。3、接收程式可以通過訊息型別有選擇地接收資料,而不是像命名管道中那樣,只能預設地接收。

2.6 訊號量(Semaphore) 訊號量是一種計數器,用於控制對多個程序共享的資源進行的訪問。它們常常被用作一個鎖機制,在某個程序正在對特定的資源進行操作時,訊號量可以防止另一個程序去訪問它。 訊號量是特殊的變數,它只取正整數值並且只允許對這個值進行兩種操作:等待(wait)和訊號(signal)。(P、V操作,P用於等待,V用於訊號) p(sv):如果sv的值大於0,就給它減1;如果它的值等於0,就掛起該程序的執行 V(sv):如果有其他程序因等待sv而被掛起,就讓它恢復執行;如果沒有其他程序因等待sv而掛起,則給它加1 簡單理解就是P相當於申請資源,V相當於釋放資源

2.7 共享記憶體(Share Memory)

共享記憶體是在多個程序之間共享記憶體區域的一種程序間的通訊方式,由IPC為程序建立的一個特殊地址範圍,它將出現在該程序的地址空間(這裡的地址空間具體是哪個地方?)中。其他程序可以將同一段共享記憶體連線到自己的地址空間中。所有程序都可以訪問共享記憶體中的地址,就好像它們是malloc分配的一樣。如果一個程序向共享記憶體中寫入了資料,所做的改動將立刻被其他程序看到。 共享記憶體是IPC最快捷的方式,因為共享記憶體方式的通訊沒有中間過程,而管道、訊息佇列等方式則是需要將資料通過中間機制進行轉換。共享記憶體方式直接將某段記憶體段進行對映,多個程序間的共享記憶體是同一塊的物理空間,僅僅對映到各程序的地址不同而已,因此不需要進行復制,可以直接使用此段空間。 注意:共享記憶體本身並沒有同步機制,需要程式設計師自己控制。

訊息佇列、訊號量以及共享記憶體的相似之處: 它們被統稱為XSI IPC,它們在核心中有相似的IPC結構(訊息佇列的msgid_ds,訊號量的semid_ds,共享記憶體的shmid_ds),而且都用一個非負整數的識別符號加以引用(訊息佇列的msg_id,訊號量的sem_id,共享記憶體的shm_id,分別通過msgget、semget以及shmget獲得),標誌符是IPC物件的內部名,每個IPC物件都有一個鍵(key_t key)相關聯,將這個鍵作為該物件的外部名。

XSI IPC和PIPE、FIFO的區別: 1、XSI IPC的IPC結構是在系統範圍內起作用,沒用使用引用計數。如果一個程序建立一個訊息佇列,並在訊息佇列中放入幾個訊息,程序終止後,即使現在已經沒有程式使用該訊息佇列,訊息佇列及其內容依然保留。而PIPE在最後一個引用管道的程序終止時,管道就被完全刪除了。對於FIFO最後一個引用FIFO的程序終止時,雖然FIFO還在系統,但是其中的內容會被刪除。 2、和PIPE、FIFO不一樣,XSI IPC不使用檔案描述符,所以不能用ls檢視IPC物件,不能用rm命令刪除,不能用chmod命令刪除它們的訪問許可權。只能使用ipcs和ipcrm來檢視可以刪除它們。

共享記憶體和記憶體對映檔案的區別: 記憶體對映檔案是利用虛擬記憶體把檔案對映到程序的地址空間中去,在此之後程序操作檔案,就像操作程序空間裡的地址一樣了,比如使用c語言的memcpy等記憶體操作的函式。這種方法能夠很好的應用在需要頻繁處理一個檔案或者是一個大檔案的場合,這種方式處理IO效率比普通IO效率要高   共享記憶體是記憶體對映檔案的一種特殊情況,記憶體對映的是一塊記憶體,而非磁碟上的檔案。共享記憶體的主語是程序(Process),作業系統預設會給每一個程序分配一個記憶體空間,每一個程序只允許訪問作業系統分配給它的哪一段記憶體,而不能訪問其他程序的。而有時候需要在不同程序之間訪問同一段記憶體,怎麼辦呢?作業系統給出了 建立訪問共享記憶體的API,需要共享記憶體的程序可以通過這一組定義好的API來訪問多個程序之間共有的記憶體,各個程序訪問這一段記憶體就像訪問一個硬碟上的檔案一樣。

記憶體對映檔案與虛擬記憶體的區別和聯絡: 記憶體對映檔案和虛擬記憶體都是作業系統記憶體管理的重要部分,兩者有相似點也有不同點。 聯絡:虛擬記憶體和記憶體對映都是將一部分內容載入到記憶體,另一部放在磁碟上的一種機制。對於使用者而言都是透明的。 區別:虛擬記憶體是硬碟的一部分,是記憶體和硬碟的資料交換區,許多程式執行過程中把暫時不用的程式資料放入這塊虛擬記憶體,節約記憶體資源。記憶體對映是一個檔案到一塊記憶體的對映,這樣程式通過記憶體指標就可以對檔案進行訪問。 虛擬記憶體的硬體基礎是分頁機制。另外一個基礎就是區域性性原理(時間區域性性和空間區域性性),這樣就可以將程式的一部分裝入記憶體,其餘部分留在外存,當訪問資訊不存在,再將所需資料調入記憶體。而記憶體對映檔案並不是區域性性,而是使虛擬地址空間的某個區域銀蛇磁碟的全部或部分內容,通過該區域對被對映的磁碟檔案進行訪問,不必進行檔案I/O也不需要對檔案內容進行緩衝處理。