共享內存:
一、概念:
共享內存可以說是最有用的進程間通信方式,也是最快的IPC形式。兩個不同進程A、B共享內存的意思是,同一塊物理內存被映射到進程A、B各自的進程地址空間。
進程A可以即時看到進程B對共享內存中數據的更新,反之亦然。由於多個進程共享同一塊內存區域,必然需要某種同步機制,互斥鎖和信號量都可以。
采用共享內存通信的一個顯而易見的好處是效率高,因為進程可以直接讀寫內存,而不需要任何數據的拷貝。
對於像管道和消息隊列等通信方式,則需要在內核和用戶空間進行四次的數據拷貝,
而共享內存則只拷貝兩次數據[1]:
1.一次從輸入文件到共享內存區,
2.另一次從共享內存區到輸出文件。
實際上,進程之間在共享內存時,並不總是讀寫少量數據后就解除映射,有新的通信時,再重新建 立共享內存區域。而是保持共享區域,直到通信完畢為止,這樣,數據內容一直保存在共享內
存中,並沒有寫回文件。共享內存中的內容往往是在解除映射時才寫回 文件的。因此,采用共享內存的通信方式效率是非常高的。
二、相關函數:
與信號量一樣,在Linux中也提供了一組函數接口用於使用共享內存,而且使用共享共存的接口還與信號量的非常相似,而且比使用信號量的接口來得簡單。它們聲明在頭文件 sys/shm.h中。
1、shmget函數
該函數用來創建共享內存,它的原型為:
int shmget(key_t key, size_t size, int shmflg);
1.第一個參數,與信號量的semget函數一樣,程序需要提供一個參數key(非0整數),它有效地為共享內存段命名。
shmget函數成功時返回一個與key相關的共享內存標識符(非負整數),用於后續的共享內存函數。調用失敗返回-1.
不相關的進程可以通過該函數的返回值訪問同一共享內存,它代表程序可能要使用的某個資源,程序對所有共享內存的訪問都是間接的,程序先通過調用shmget函數並提供一個鍵,再由
系統生
成一個相應的共享內存標識符(shmget函數的返回值),只有shmget函數才直接使用信號量鍵,所有其他的信號量函數使用由semget函數返回的信號量標識符。
2.第二個參數,size以字節為單位指定需要共享的內存容量
3.第三個參數,shmflg是權限標志,它的作用與open函數的mode參數一樣,如果要想在key標識的共享內存不存在時,創建它的話,可以與IPC_CREAT做或操作。
共享內存的權限標志與文件的讀寫權限一樣,舉例來說,0644,它表示允許一個進程創建的共享內存被內存創建者所擁有的進程向共享內存讀取和寫入數據,同時其他用戶創建的進程只能讀取共
享內存。
2、shmat函數
第一次創建完共享內存時,它還不能被任何進程訪問,shmat函數的作用就是用來啟動對該共享內存的訪問,並把共享內存連接到當前進程的地址空間。它的原型如下:
void *shmat(int shm_id, const void *shm_addr, int shmflg);
第一個參數,shm_id是由shmget函數返回的共享內存標識。
第二個參數,shm_addr指定共享內存連接到當前進程中的地址位置,通常為空,表示讓系統來選擇共享內存的地址。
第三個參數,shm_flg是一組標志位,通常為0。
調用成功時返回一個指向共享內存第一個字節的指針,如果調用失敗返回-1.
3、shmdt函數
該函數用於將共享內存從當前進程中分離。注意,將共享內存分離並不是刪除它,只是使該共享內存對當前進程不再可用。它的原型如下:
int shmdt(const void *shmaddr);
參數shmaddr是shmat函數返回的地址指針,調用成功時返回0,失敗時返回-1.
4、shmctl函數
與信號量的semctl函數一樣,用來控制共享內存,它的原型如下:
int shmctl(int shm_id, int command, struct shmid_ds *buf);
第一個參數,shm_id是shmget函數返回的共享內存標識符
第二個參數,command是要采取的操作,它可以取下面的三個值 :
IPC_STAT:把shmid_ds結構中的數據設置為共享內存的當前關聯值,即用共享內存的當前關聯值覆蓋shmid_ds的值。
IPC_SET:如果進程有足夠的權限,就把共享內存的當前關聯值設置為shmid_ds結構中給出的值
IPC_RMID:刪除共享內存段
第三個參數,buf是一個結構指針,它指向共享內存模式和訪問權限的結構。
shmid_ds結構至少包括以下成員:
struct shmid_ds
{
uid_t shm_perm.uid;
uid_t shm_perm.gid;
mode_t shm_perm.mode;
};
三、實例:
關於共享內存的實例見下面博客,已經很好了,我也就不在班門弄斧了:
賜教!
