一、共享記憶體實現程序間通訊的基礎
以32位系統為例,其可定址的最大記憶體為4gib(2^32),這4gib記憶體就是常說的虛擬記憶體。
linux核心將這4gib的虛擬記憶體分為兩部分:底部較大的部分用於使用者程序,即使用者空間(user space);頂部專用於核心,即核心空間(kernel space):
如果劃分比例為3 : 1,則0~3gib用於使用者空間,1gib用於核心空間。當然,這個分割比是可以修改的。
在建立程序的時候,每個程序分配獨有的3gib虛擬記憶體,且彼此無法訪問對方的這部分記憶體內容(所以需要程序間通訊)。
而1gib的核心空間卻是各個程序"共享",之所以加引號是因為程序無法直接訪問,必須通過系統呼叫陷入核心進行訪問。
共享記憶體的通訊方式就是基於此實現。
二、經典例項
共享記憶體這種程序間通訊方式的乙個典型的實現就是android中的ipc工具:binder。
binder利用linux自身的記憶體管理技術,確保了資料在核心空間傳遞過程中的可靠性;其次,由於使用者空間無法訪問核心空間,這就解決了資料的安全性。
binder實現為linux的乙個驅動,註冊成功後建立"/dev/binder"節點,並提供以下操作介面:
static const struct file_operations binder_fops = ;
自然,跟主題有關的就是binder_mmap()函式,使用者空間通過
mmap()系統呼叫陷入到
binder_mmap()函式,完成使用者空間和核心空間的記憶體對映:
struct binder_state *binder_open(size_t mapsize)
binder_mmap()函式:
static int binder_mmap(struct file *filp, struct vm_area_struct *vma)
file的private_data成員在呼叫open()的時候進行賦值,儲存乙個struct binder_proc物件指標,這裡將其取出。
private_data的初始化過程:
static int binder_open(struct inode *nodp, struct file *filp)
在使用者空間呼叫mmap()時指定對映的記憶體的大小為mapsize,vma->vm_start和vma->vm_end分別指向使用者空間對映的buffer的起始位址和結束位址。
通過get_vm_area(),在核心的虛擬對映區尋找乙個連續的、(vma->vm_end - vma->vm_start)大小的區域,返回給area。
area->addr儲存著這部分區域的起始位址。
執行完proc->buffer = area->addr後,proc->buffer就有了核心空間對映的buffer(用於
接收ipc資料
)的起始位址。
proc->user_buffer_offset,儲存使用者空間buffer位址和核心空間buffer位址的偏移,由先前知識可知,偏移量為乙個負值。
有了這個偏移量,就把這兩部分的對映區域聯絡在了一起。
以上說的都是虛(擬記憶體)的,要幹事畢竟還得來實(物理記憶體)的,接下來就是把上述buffer對映到物理記憶體上。
((vma->vm_end - vma->vm_start) / page_size)計算需要的頁數。頁是kernel管理物理記憶體的基本單位,由struct page表示。
proc->pages用於為管理記憶體的pages分配記憶體。
binder_update_page_range()用於分配物理頁,kernel通過頁表這一方式實現實體地址和虛擬位址的對映,這部分執行後:
之後,不同程序間通過binder這種共享記憶體的方式就可進行ipc。
Linux程序間通訊(2) 共享記憶體
共享記憶體是程序間通訊最簡單最快速的方式 訪問共享記憶體區域和訪問程序獨有的記憶體區域一樣快,並不需要通過系統呼叫或者其他需要切入核心的過程來完成。同時也避免了對資料的各種不必要的複製。使用步驟 1 首先要分配一塊共享記憶體,使用shmget函式 函式定義 int shmget key t key,...
程序間通訊 共享記憶體
下面是自己寫的乙個簡單的共享記憶體的程序間通訊的例子。共享記憶體是用於程序間大量資料共享的一種方法。include include include include include include int main if buf1 shmat shmid,0,0 void 1 strcpy buf1,...
程序間通訊 共享記憶體
共享記憶體是被多個程序共享的一部分物理記憶體。共享記憶體是程序間共享資料的一種最快的方式,乙個程序向共享記憶體區域寫入資料,共享這個記憶體區域的所有程序就可以立刻看到其中的內容。共享記憶體實現分兩個步驟 建立共享記憶體,使用shmget函式 對映共享記憶體,使用shmat函式 共享記憶體是一種最為高...