IPC_記憶體共用

來源:互聯網
上載者:User

記憶體共用筆記:
1.它允許兩個不相關的的進程訪問同一個邏輯記憶體。(記憶體是共用的)
2.它並未提供同步機制,所以我們要通過其他同步手段達到記憶體訪問的同步效果。(一般通過傳遞小訊息來達到同步。)
3.共用記憶體的函數類似於訊號量函數(IPC機制的函數都具有相似之處)
void *shmat(int shm_id, const void *shm_addr, int shmflg);
int shmctl(int shm_id, int cmd, struct shmid_ds *buf);
int shmdt(const void *shm_addr);
int shmget(key_t key, size_t size, int shmflg);          #include <sys/shm.h>
4.建立共用記憶體:
shmget: key,size位元組為單位的指定共用記憶體大小,IPC_CREAT和一個許可權標誌位按|運算建立一個新共用記憶體段。許可權標誌位就給定了記憶體讀寫權限;成功返回非負整數,失敗返回-1
shmat:建立好後,並不能被進程共用,我們必須讓它映射到我們本進程的進程記憶體空間才行。這個方法就是這個作用鳥。
*shm_addr:通常給null 指標,表示系統自己選定一個進程地址來作為共用記憶體的映射地址。
shmflg:通常我們給0,還有2種給法:shm_rnd(和shm_addr相關) and  shm_rdonly唯讀:如果建立的存取權限是可寫的,但是這裡又設定了是rdonly,那麼也是rdonly的。
成功返回首地址,失敗返回-1.
shmdt:解映射:作用是將共用記憶體從當前進程中分離,使得該進程無法使用記憶體共用。成功返回0,失敗返回-1.
shmctl:command:IPC_STAT(好像和IPC_SET一樣的作用耶) IPC_SET設定值 IPC_RMID刪除(這個時候struct buf給0即可) 
*buf :指向包含共用記憶體模式和存取權限的結構。
 成功0,失敗-1.s
注意:如果shmctl刪除一個正處於連結狀態的共用記憶體時,通常這個共用記憶體段還能夠繼續使用,直到它從最後一個進程中分離為止。(不過這個並未標準化,所以不要太依賴這個概念)

實際編程中,我們通常使用訊號量,傳遞訊息(管道or ipc訊息佇列),產生訊號等方法來達到對共用記憶體的同步訪問。

 以下是轉的(補充):

1. 資料結構

與訊息佇列和訊號量集合類似,核心為每一個共用記憶體段(存在於它的地址空間)維護著一個特殊的資料結構shmid_ds,這個結構在include/linux/shm.h中定義如下:

/* 在系統中 每一個共用記憶體段都有一個shmid_ds資料結構. */

struct shmid_ds {

struct ipc_perm shm_perm;        /* 操作許可權 */

int     shm_segsz;               /* 段的大小(以位元組為單位) */

time_t  shm_atime;               /* 最後一個進程附加到該段的時間 */

time_t  shm_dtime;               /* 最後一個進程離開該段的時間 */

time_t  shm_ctime;               /* 最後一次修改這個結構的時間 */

unsigned short  shm_cpid;        /*建立該段進程的 pid */

unsigned short  shm_lpid;        /* 在該段上操作的最後一個進程的pid */

short   shm_nattch;              /*當前附加到該段的進程的個數  */

/* 下面是私人的 */

unsigned short   shm_npages;     /*段的大小(以頁為單位) */

unsigned long   *shm_pages;      /* 指向frames -> SHMMAX的指標數組 */

struct vm_area_struct *attaches; /* 對共用段的描述 */

};

------

2. 共用記憶體的處理過程      

某個進程第一次訪問共用虛擬記憶體時將產生缺頁異常。這時,Linux 找出描述該記憶體的 vm_area_struct 結構,該結構中包含用來處理這種共用虛擬記憶體段的處理函數地址。共用記憶體缺頁異常處理代碼對shmid_ds 的頁表項表進行搜尋,以便查看是否存在該共用虛擬記憶體的頁表項。如果沒有,系統將分配一個物理頁並建立頁表項,該頁表項加入 shmid_ds 結構的同時也添加到進程的頁表中。這就意味著當下一個進程試圖訪問這頁記憶體時出現缺頁異常,共用記憶體的缺頁異常處理代碼則把新建立的物理頁給這個進程。(因此說,第一個進程對共用記憶體的存取引起建立新的物理頁面,而其它進程對共用記憶體的存取引起把那個頁加添加到它們的地址空間。)

當某個進程不再共用其虛擬記憶體時,利用系統調用將共用段從自己的虛擬位址地區中移去,並更新進程頁表。當最後一個進程釋放了共用段之後,系統將釋放給共用段所分配的物理頁。

當共用的虛擬記憶體沒有被鎖定到實體記憶體時,共用記憶體也可能會被交換到交換區中。

--------

系統調用: shmctl()

原型: int shmctl ( int shmqid, int cmd, struct shmid_ds *buf );

返回:成功為 0 ,   失敗 為-1

這個特殊的調用和semctl()調用幾乎相同,因此,這裡不進行詳細的討論。有效命令的值是:

IPC_STAT :檢索一個共用段的shmid_ds結構,把它存到buf參數的地址中。

IPC_SET :對一個共用段來說,從buf 參數中取值設定shmid_ds結構的ipc_perm域的值。

IPC_RMID :把一個區段標記為刪除

IPC_RMID 命令實際上不從核心刪除一個段,而是僅僅把這個區段標記為刪除,實際的刪除發生在最後一個進程離開這個共用段時。

當一個進程不再需要共用記憶體段時,它將調用shmdt()系統調用取消這個段,但是,這並不是從核心真正地刪除這個段,而是把相關shmid_ds結構的 shm_nattch域的值減1,當這個值為0時,核心才從物理上刪除這個共用段。

之所以記憶體共用是最快速的IPC機制,是因為讀它的訪問是不需要涉及核心的。所以快。但因此我們也要提供對他的同步機制。

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.