共享記憶體區是最快的可用ipc形式。它允許多個不相關的程序去訪問同一部分邏輯記憶體。如果需要在兩個執行中的程序之間傳輸資料,共享記憶體將是一種效率極高的解決方案。一旦這樣的記憶體區對映到共享它的程序的位址空間,這些程序間資料的傳輸就不再涉及核心。這樣就可以減少系統呼叫時間,提高程式效率
共享記憶體是由ipc為乙個程序建立的乙個特殊的位址範圍,它將出現在程序的位址空間中。其他程序可以把同一段共享記憶體段「連線到」它們自己的位址空間裡去。所有程序都可以訪問共享記憶體中的位址。如果乙個程序向這段共享記憶體寫了資料,所做的改動會立刻被有訪問同一段共享記憶體的其他程序看到。
要注意的是共享記憶體本身沒有提供任何同步功能。也就是說,在第乙個程序結束對共享記憶體的寫操作之前,並沒有什麼自動功能能夠預防第二個程序開始對它進行讀操作。共享記憶體的訪問同步問題必須由程式設計師負責。可選的同步方式有互斥鎖、條件變數、讀寫鎖、紀錄鎖、訊號燈。
相關函式
1mmap()函式
23 標頭檔案:#include 4 函式原型:void *mmap(void *addr, size_t len, int prot, int flag, int
filedes, off_t off);56
引數:7
addr 指向對映儲存區的起始位址;
8len 對映的位元組
9prot 對對映儲存區的保護要求
10flag 標誌位
11filedes 要被對映檔案的描述符
12off 要對映位元組在檔案中的起始偏移量
1314
15如果addr不是null,則給核心乙個提示,應該從什麼位址開始對映,核心會選擇addr之上的某個合適的位址開始對映。建立對映後,真正的
16對映首位址通過返回值可以得到。off引數是從檔案的什麼位置開始對映,必須是頁大小的
17整數倍(在32位體系統結構上通常是4k)。
18prot引數有四種取值:
19prot_exec表示對映的這一段可執行,例如對映共享庫
20prot_read表示對映的這一段可讀
21prot_write表示對映的這一段可寫
22prot_none表示對映的這一段不可訪問
23flag引數有很多種取值,這裡只講兩種,
24map_shared多個程序對同乙個檔案的對映是共享的,乙個程序對對映的記憶體做了修改,另乙個程序也會看到這種變化。
25map_private多個程序對同乙個檔案的對映不是共享的,乙個程序對對映的記憶體做了修改,另乙個程序並不會看到這種變化,也不會
26 真的寫到檔案中去。
注:當程序終止時,該程序的對映記憶體會自動解除,也可以呼叫munmap解除對映。munmap成功返回0,出錯返回-1。
1核心的虛存演算法保持記憶體對映檔案(一般在硬碟上)與記憶體對映區(在記憶體中)的同步(前提它是map_shared記憶體區)。這就是說,如果我們修改了記憶體對映到某個檔案的記憶體區中某個位置的內容,那麼核心將在稍後某個時刻相應地更新檔案。然而有時候我們希望確信硬碟上的檔案內容與記憶體對映區中的檔案內容一致,於是呼叫msync來執行這種同步。munmap()函式
2功能:解除儲存對映
3 標頭檔案:#include 4 函式原型:int
munmap(caddr_t addr,size_t len);
5引數:
6addr 指向對映儲存區的起始位址
7len 對映的位元組
8 返回值:若成功則返回0,若出錯則返回-1910
其中addr引數是由mmap返回的位址,len是對映區的大小。再次訪問這些位址導致向呼叫程序產生乙個sigse**訊號。如果被對映區是使用
11 map_private標誌對映的,那麼呼叫程序對它所作的變動都被丟棄掉。
1編譯執行:msync()函式
2功能:同步檔案到儲存器
3 標頭檔案:#include 4 函式原型:int msync(void *addr,size_t len,int
flags);
5引數:
6addr 指向對映儲存區的起始位址
7len 對映的位元組
8flags 引數為ms_async(執行非同步寫),ms_sync(執行同步寫),ms_invalidate(使快取記憶體的資料實效)。
9其中ms_async和ms_sync這兩個常值中必須指定乙個,但不能都指定。它們的差別是,一旦寫操作已由核心排入佇列,
10ms_async即返回,而ms_sync則要等到寫操作完成後才返回。如果還指定了ms_invalidate,那麼與其最終拷貝不一致的檔案資料的
11所有記憶體中拷貝都失效。後續的引用將從檔案取得資料。
12 返回值: 若成功則返回0,若出錯則返回-1
1314
15memcpy()函式
16功能: 複製對映儲存區
17 標頭檔案: #include
18 函式原形: void *memcpy(void *dest,const
void *src,size_t n);
19引數:
20dest 待複製的對映儲存區
21src 複製後的對映儲存區
22n 待複製的對映儲存區的大小
示例**:
/*mycp.c
*/#include
#include
#include
#include
#include
#include
#include
#include
int main(int argc,char *ar**)
/*開啟原檔案
*/if((fdin=open(ar**[1],o_rdonly))<0
) perror(ar**[
1]);
/*建立並開啟目標檔案
*/if((fdout=open(ar**[2],o_rdwr|o_creat|o_trunc))<0
) perror(ar**[
2]);
/*獲得檔案大小資訊
*/if(fstat(fdin,&statbuf)<0
) printf(
"fstat error");
/*初始化輸出對映儲存區
*/if(lseek(fdout,statbuf.st_size-1,seek_set)==-1
) printf(
"lseek error");
if(write(fdout,"
1",1)!=1
) printf(
"write error");
/*對映原檔案到輸入的對映儲存區
*/if((src=mmap(0,statbuf.st_size,prot_read,map_shared,fdin,0))==map_failed)
printf(
"mmap error");
/*對映目標檔案到輸出的對映儲存區
*/if((dst=mmap(0,statbuf.st_size,prot_read|prot_write,map_shared,fdout,0)) ==map_failed)
printf(
"mmap error");
memcpy(dst,src,statbuf.st_size);
/*複製對映儲存區
*/munmap(src,statbuf.st_size);
/*解除輸入對映
*/munmap(dst,statbuf.st_size);
/*解除輸出對映
*/close(fdin);
close(fdout);
}
1 root@linux:/mnt/hgfs/c_libary# vi mycp.c2 root@linux:/mnt/hgfs/c_libary# gcc -o mycp mycp.c
3 root@linux:/mnt/hgfs/c_libary# ./mycp test1.txt test2.txt
4 root@linux:/mnt/hgfs/c_libary# more test2.txt
5 hello world!
IPC通訊之共享記憶體
共享記憶體就是使得多個程序可以訪問同一塊記憶體空間,是最快的可用 ipc形式。是針對其他通訊機制執行效率較低而設計的。往往與其它通訊機制,如訊號量結合使用,來達到程序間的同步及互斥。我們通過一張圖來表示這個關係 共享記憶體和訊息佇列,訊號量一樣都屬於xsi ipc。核心都為他們維護了一套資料結構 同...
多程序通訊(IPC) 共享記憶體
1 共享記憶體介紹 共享記憶體可以說是最有用的程序間通訊方式,也是最快的ipc形式。兩個不同程序a b共享記憶體的意思是,同一塊物理記憶體被對映到程序a b各自的程序位址空間。程序a可以即時看到程序b對共享記憶體中資料的更新,反之亦然。由於多個程序共享同一塊記憶體區域,必然需要某種同步機制,互斥鎖和...
程序間通訊IPC 共享記憶體
共享記憶體 共享記憶體 就是開闢一段物理記憶體使多個程序共享 是程序間最高效的傳輸方式 共享記憶體必須結合其他方式來實現程序間的同步 程式設計步驟 1 開闢一段共享記憶體 int shmget key t key,size t size,int shm key t key ftok a stat s...