1. 程式人生 > >IPC通訊:Posix共享記憶體1

IPC通訊:Posix共享記憶體1

 共享記憶體區是最快的可用IPC形式。它允許多個不相關的程序去訪問同一部分邏輯記憶體。如果需要在兩個執行中的程序之間傳輸資料,共享記憶體將是一種效率極高的解決方案。一旦這樣的記憶體區對映到共享它的程序的地址空間,這些程序間資料的傳輸就不再涉及核心。這樣就可以減少系統呼叫時間,提高程式效率

  共享記憶體是由IPC為一個程序建立的一個特殊的地址範圍,它將出現在程序的地址空間中。其他程序可以把同一段共享記憶體段“連線到”它們自己的地址空間裡去。所有程序都可以訪問共享記憶體中的地址。如果一個程序向這段共享記憶體寫了資料,所做的改動會立刻被有訪問同一段共享記憶體的其他程序看到。

  要注意的是共享記憶體本身沒有提供任何同步功能。也就是說,在第一個程序結束對共享記憶體的寫操作之前,並沒有什麼自動功能能夠預防第二個程序開始對它進行讀操作。共享記憶體的訪問同步問題必須由程式設計師負責。可選的同步方式有互斥鎖、條件變數、讀寫鎖、紀錄鎖、訊號燈。

相關函式

複製程式碼
 1 mmap()函式
 2 功能:把一個檔案或一個Posix共享記憶體區物件對映到呼叫程序的地址空間。
 3 標頭檔案:#include <sys/mman.h>
 4 函式原型:void *mmap(void *addr, size_t len, int prot, int flag, int filedes, off_t off);
 5 返回值:如果mmap成功則返回對映首地址,如果出錯則返回常數MAP_FAILED。 
 6 引數:
 7     addr    指向對映儲存區的起始地址;
 8     len        對映的位元組
 9     prot    對對映儲存區的保護要求
10 flag 標誌位 11 filedes 要被對映檔案的描述符 12 off 要對映位元組在檔案中的起始偏移量 13 14 引數解釋如下:整體相當於磁碟檔案的對應長度搬移到記憶體中。如果addr引數為NULL,核心會自己在程序地址空間中選擇合適的地址建立對映。 15 如果addr不是NULL,則給核心一個提示,應該從什麼地址開始對映,核心會選擇addr之上的某個合適的地址開始對映。建立對映後,真正的 16 對映首地址通過返回值可以得到。off引數是從檔案的什麼位置開始對映,必須是頁大小的 17 整數倍(在32位體系統結構上通常是4K)。
18 prot引數有四種取值: 19 PROT_EXEC表示對映的這一段可執行,例如對映共享庫 20 PROT_READ表示對映的這一段可讀 21 PROT_WRITE表示對映的這一段可寫 22 PROT_NONE表示對映的這一段不可訪問 23 flag引數有很多種取值,這裡只講兩種, 24 MAP_SHARED多個程序對同一個檔案的對映是共享的,一個程序對對映的記憶體做了修改,另一個程序也會看到這種變化。 25 MAP_PRIVATE多個程序對同一個檔案的對映不是共享的,一個程序對對映的記憶體做了修改,另一個程序並不會看到這種變化,也不會 26 真的寫到檔案中去。
複製程式碼

注:當程序終止時,該程序的對映記憶體會自動解除,也可以呼叫munmap解除對映。munmap成功返回0,出錯返回-1

複製程式碼
 1 munmap()函式
 2 功能:解除儲存對映
 3 標頭檔案:#include <sys/mman.h>
 4 函式原型:int munmap(caddr_t addr,size_t len);
 5 引數:
 6     addr   指向對映儲存區的起始地址
 7     len    對映的位元組
 8 返回值:若成功則返回0,若出錯則返回-1
 9 
10 其中addr引數是由mmap返回的地址,len是對映區的大小。再次訪問這些地址導致向呼叫程序產生一個SIGSEGV訊號。如果被對映區是使用
11 MAP_PRIVATE標誌對映的,那麼呼叫程序對它所作的變動都被丟棄掉。 
複製程式碼

  核心的虛存演算法保持記憶體對映檔案(一般在硬碟上)與記憶體對映區(在記憶體中)的同步(前提它是MAP_SHARED記憶體區)。這就是說,如果我們修改了記憶體對映到某個檔案的記憶體區中某個位置的內容,那麼核心將在稍後某個時刻相應地更新檔案。然而有時候我們希望確信硬碟上的檔案內容與記憶體對映區中的檔案內容一致,於是呼叫msync來執行這種同步。

複製程式碼
 1 msync()函式
 2 功能:同步檔案到儲存器
 3 標頭檔案:#include <sys/mman.h>
 4 函式原型:int msync(void *addr,size_t len,int flags);
 5 引數:
 6     addr  指向對映儲存區的起始地址
 7     len   對映的位元組
 8     flags 引數為MS_ASYNC(執行非同步寫),MS_SYNC(執行同步寫),MS_INVALIDATE(使快取記憶體的資料實效)。
 9           其中MS_ASYNC和MS_SYNC這兩個常值中必須指定一個,但不能都指定。它們的差別是,一旦寫操作已由核心排入佇列,
10           MS_ASYNC即返回,而MS_SYNC則要等到寫操作完成後才返回。如果還指定了MS_INVALIDATE,那麼與其最終拷貝不一致的檔案資料的
11           所有記憶體中拷貝都失效。後續的引用將從檔案取得資料。
12 返回值:    若成功則返回0,若出錯則返回-1
13 
14 
15 memcpy()函式
16 功能:    複製對映儲存區
17 標頭檔案:    #include <string.h>
18 函式原形:    void *memcpy(void *dest,const void *src,size_t n);
19 引數:    
20     dest   待複製的對映儲存區
21     src    複製後的對映儲存區
22     n      待複製的對映儲存區的大小
23 返回值:    返回dest的首地址
複製程式碼

示例程式碼:

複製程式碼
/*mycp.c*/
#include <unistd.h>
#include <stdlib.h>
#include <string.h>
#include <stdio.h>
#include <fcntl.h>
#include <sys/mman.h>
#include <sys/stat.h>
#include <sys/types.h>

int main(int argc,char *argv[])
{
    int fdin,fdout;
    void *src,*dst;
    struct stat statbuf;

    if(argc!=3)
    {
        printf("please input two file!\n");
        exit(1);
    }
    /*開啟原檔案*/
    if((fdin=open(argv[1],O_RDONLY))<0) 
        perror(argv[1]);
  /*建立並開啟目標檔案*/
    if((fdout=open(argv[2],O_RDWR|O_CREAT|O_TRUNC))<0)
        perror(argv[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 [email protected]:/mnt/hgfs/C_libary# vi mycp.c
2 [email protected]:/mnt/hgfs/C_libary# gcc -o mycp mycp.c
3 [email protected]:/mnt/hgfs/C_libary# ./mycp test1.txt test2.txt
4 [email protected]:/mnt/hgfs/C_libary# more test2.txt
5 hello world!

相關推薦

IPC通訊:Posix共享記憶體1

 共享記憶體區是最快的可用IPC形式。它允許多個不相關的程序去訪問同一部分邏輯記憶體。如果需要在兩個執行中的程序之間傳輸資料,共享記憶體將是一種效率極高的解決方案。一旦這樣的記憶體區對映到共享它的程序的地址空間,這些程序間資料的傳輸就不再涉及核心。這樣就可以減少系統呼叫

IPC通訊:Posix共享記憶體

http://www.cnblogs.com/polestar/archive/2012/04/23/2466003.html  共享記憶體區是最快的可用IPC形式。它允許多個不相關的程序去訪問同一部分邏輯記憶體。如果需要在兩個執行中的程序之間傳輸資料,共享記憶體將是一

IPCPosix共享記憶體詳解

1.概念 共享記憶體區,按標準可分為Posix共享記憶體區和System V共享記憶體區,兩者在概念上類似。 Posix 表示可移植作業系統介面(Portable Operating System Interface ,縮寫為 POSIX ),POSIX標準定義了作業系統

IPCPosix共享記憶體區與mmap記憶體對映

共享記憶體是一種IPC形式,與其它IPC機制如管道、訊息佇列等相比,資料不必在程序與核心間多次交換,程序間通訊的速度更快。當共享記憶體區對映到共享它的程序的地址空間時,再加以一些同步控制,這些程序就可以進行資料傳送了。mmap函式提供了記憶體對映功能,可以把一個

Linux程序間通訊POSIX共享記憶體

共享記憶體是最高效的IPC機制,因為它不涉及程序之間的任何資料傳輸。這種高效率帶來的問題是,我們必須用其他輔助手段來同步程序對共享記憶體的訪問,否則會產生競態條件。因此,共享記憶體通常和其他程序間通訊方式一起使用。 Linux下有三種共享記憶體的IPC技術:S

【Linux】程序間通訊IPC)之共享記憶體詳解與測試用例

學習環境centos6.5 Linux核心2.6 什麼是共享記憶體 共享記憶體允許兩個或更多程序訪問同一塊記憶體。當一個程序改變了這塊記憶體中的內容的的時候,其他程序都會察覺到這個更改。 效率: 因為所有程序共享同一塊記憶體,共享記憶體在各種程序

程序間通訊共享記憶體

一、共享記憶體的定義和原理 1、共享記憶體的定義   顧名思義,共享記憶體就是允許兩個不相關的程序訪問同一個邏輯記憶體。共享記憶體是在兩個正在執行的程序之間共享和傳遞資料的一種非常有效的方式。不同程序之

Linux系統程式設計——程序間通訊共享記憶體

概述 共享記憶體是程序間通訊中最簡單的方式之一。共享記憶體允許兩個或更多程序訪問同一塊記憶體,就如同 malloc() 函式向不同程序返回了指向同一個實體記憶體區域的指標。當一個程序改變了這塊地址中的內容的時候,其它程序都會察覺到這個更改。 共享記憶體的特點: 1)共

Linux IPC——簡單應用 共享記憶體(Share Memory)

目錄   一:共享記憶體 1.1定義 1.2優缺點 1.2.1 優點 1.2.2缺點 1.3共享記憶體結構維護 1.4共享記憶體的通訊原理 二:相關函式介面 2.1 Linux命令 2.1.1檢視系統中的共享儲存段  2.1.2

共享記憶體1.0(mmap函式)

#include"common.h" int main() { int i,zero=1; int *ptr=&zero; if(fork()==0) { for(i=0;i<100;i++) { printf("child: %d\n

程序間通訊共享記憶體(Share Memory)

為了實現多個程序之間的通訊,我們可以用系統頁面檔案來作為共享記憶體檔案。 1.首先我們建立第一個程序,用系統函式CreateFileMapping建立共享記憶體檔案,用函式MapViewOfFile

Actor 併發模型 & "不要通過共享記憶體通訊,而應該通過通訊共享記憶體"

Actor的原理: 先從著名的c10k問題談起。有一個叫Dan Kegel的人在網上(http://www.kegel.com/c10k.html)提出:現在的硬體應該能夠讓一臺機器支援10000個併發的client。然後他討論了用不同的方式實現大規模併發服務的技術,歸納起來就是兩種方式:一個client一個

程序間通訊共享記憶體(程式碼實現)

共享記憶體:1.共享記憶體就是允許兩個不相關的程序訪問同一個邏輯記憶體;                     2.共享記憶體是在兩個正在執行的程序之間共享和傳遞資料的一種最有效的方式;                     3.不同程序之間共享的記憶體通常安排為同一段

【Qt】Qt之程序間通訊共享記憶體)【轉】

簡述 上一節中,我們分享下如何利用Windows訊息機制來進行不同程序間的通訊。但是有很多侷限性,比如:不能跨平臺,而且必須兩個程序同時存在才可以,要麼程序A發了訊息誰接收呢? 下面我們來分享另外一種跨平臺的進行間通訊的方式-Shared Memory(共享記憶體)。 簡述 注意事項

執行緒通訊機制---共享記憶體:訊息傳遞

在併發程式設計中,我們必須考慮的問題時如何在兩個執行緒間進行通訊。這裡的通訊指的是不同的執行緒之間如何交換資訊。 目前有兩種方式: 1、共享記憶體 2、訊息傳遞(actor 模型) 共享記憶體 共享記憶體這種方式比較常見,我們經常會設定一個共享變數。然後多個執行緒去操作

Windows程序間通訊共享記憶體

之前自己做的一個專案涉及到程序間通訊問題,我採用的是SOCKET方式。面試的時候有問過為什麼不採用其他方式。好吧,其實發現共享記憶體更方便一點。於是自己寫了一下,並且做了個測試介面。 寫的程式可以在這裡下載下載程式 程式啟動會獲得自身的視窗控制代碼,另外可以輸入一個視

域套接字通訊共享記憶體通訊效能比較

最近碰到一個問題,兩個程序間需要實時交換一些資料,資料量不是很大,就72個位元組。當時估計簡單起見,用的是域套接字的方式。 後續效能測試的時候,忽然發現當網路包併發量很大時,效能忽然大幅下降,用strace跟蹤發現,忽然有好多的read,write操作,檢視程式碼跟蹤到此處

程序間通訊之-共享記憶體Shared Memory--linux核心剖析(十一)

共享記憶體 共享記憶體是程序間通訊中最簡單的方式之一。 共享記憶體是系統出於多個程序之間通訊的考慮,而預留的的一塊記憶體區。 共享記憶體允許兩個或更多程序訪問同一塊記憶體,就如同 malloc() 函式向不同程序返回了指向同一個實體記憶體區域的指標。當

54.Linux/Unix 系統程式設計手冊(下) -- POSIX 共享記憶體

1.概述 前面介紹了2種允許無關程序共享記憶體區域以便執行 IPC 的技術:System V 共享記憶體和共享檔案對映。這2種技術都有一些不足: 1.System V 共享記憶體模型使用的是鍵和識別符號,這與標準的 Unix IO 模型使用檔名和描述符的做法不一致。這種差

程序間通訊共享記憶體:shm

shm程式碼 #include <stdio.h> #include <sys/ipc.h> #include <sys/shm.h> struct shm/