共享內存區的使用

共享內存區:

共享內存區時IPC形式中最快的。由於當共享內存區映射到共享它的進程的地址空間,這些進程間
數據的傳遞就不在涉及內核(進程不在經過執行任何進入內核的系統調用來傳遞數據)。

與其餘IPC形式相比,進程經過共享內存區傳遞數據的步驟:

 

注意:默認狀況下,經過fork()派生的子進程並不與其父進程共享內存區

使用共享內存區時所需的函數:

mmap()函數:

爲什麼使用mmap()函數:
1.使用普通文件以提供內存映射I/O
2.使用特殊文件以提供匿名內存映射
3.使用shm_open以提供無親緣關係進程間的Posix共享內存區
#include <sys/mman.h>

// 將一個文件或一個Posix共享內存區對象映射到調用進程的地址空間
// 成功返回被映射區的起始地址,出錯返回MAP_FAILED
void *mmap(void *addr, size_t len, int prot, int flags, int fd, off_t offset);
// addr:能夠指定描述符fd應被映射到的進程內空間的起始地址(一般addr被指定爲NULL,讓內核本身選擇起始地址)
// len: 映射到調用進程地址空間的字節數,它從被映射文件開頭其第offset個字節出開始算
// prot:指定內存映射區保護(PROT_READ可讀、PROT_WRITE可寫、PROT_EXEC可執行、PROT_NONE不可訪問)
// flags:指定進程對被映射數據所作的修改是否對共享該對象的其餘進程共享,其值以下:
//     必須爲MAP_SHARED(共享)或MAP_PRIVATE(私有)之一,能夠或上(|)MAP_FIXED(準確的解釋addr值)
//     共享即意味着該修改改變該共享對象的底層支撐對象(如某個文件,該文件被映射,此文件爲底層支撐對象)
// fd: 被映射的文件的描述符
// offset: 偏移量(通常該值爲0)
// 爲了可移植考慮,通常將addr指定爲空指針,而且不指定MAP_FIXED

munmap()函數:

#include <sys/mman.h>

// 刪除一個映射關係、
// 成功返回0,出錯返回-1
int munmap(void *addr, size_t len);
// addr:是由mmap()返回的地址
// len:映射區大小

msync()函數:

官方說明html

#include <sys/mman.h>

// 使得硬盤中的文件與內存映射區內容一致,使用msync()執行同步
// 成功返回0,出錯返回-1
int msync(void *addr, size_t len, int flags);
/*
關於addr和len參數的說明
The addr argument is the address of the first page of mapped memory to be synchronized.
The address must be on a page boundary, but need not be the first byte of the entire 
area mapped to a file. 
The len argument specifies the number of bytes of memory to be synchronized. If the length
does not specify an integral number of pages, it is rounded up to do so. The length need
not specify the entire area of mapped memory. 
*/
// flags: 取值爲MS_ASYNC(異步寫)或MS_SYNC(同步寫)之一,還能夠或上MS_INVALIDATE()

Posix共享內存區:

Posix提供的兩種在無親緣關係的進程間共享內存區的方法:
1.內存映射文件:由open()打開某個文件,再由mmap()將獲得的描述符映射到當前進程地址空間中
的一個文件。
2.共享內存區對象:有shm_open()打開一個Posix IPC名字(多是文件系統中的一個路徑名),所返
回的描述符有mmap()映射到當前進程的地址空間。

shm_open()函數:

#include <sys/mman.h>

// 建立一個新的共享內存區對象,或打開一個已存在的共享內存區對象
// 成功返回非負描述符,出錯返回-1
int shm_open(const char *name, int oflag, mode_t mode);
// name: Posix IPC名字,name參數隨後也做爲但願共享該內存區的任何其餘進程使用
// oflag: 該參數必須含有O_RDONLY(只讀)或O_RDWR(讀寫),能夠或上O_CREAT,O_EXCL,O_TRUNC
// 若 oflag = O_RDWD | O_TRUNC,且所需共享內存區對象已存在,那麼它的長度被截短成0
// mode:權限位,在沒有指定O_CREAT時mode能夠爲0,當指定了O_CREAT後,mode參數必須指定

建立新的IPC對象所用的mode常值:
S_IRUSR    用戶(屬主)讀
S_IWUSR    用戶(屬主)寫
S_IRGRP    屬組讀
S_IWGRP    屬組寫
S_IROTH    其餘用戶讀
S_IWOTH    其餘用戶寫數據結構

shm_unlink()函數:

#include <sys/mman.h>

// 刪除一個共享內存區對象名字,防止後續的open調用成功(與unlink、ma_unlink、sem_unlink相似)
// 成功返回0,出錯返回-1
int shm_unlink(const char *name);

System V共享內存區:

與Posix共享內存區相似,只不過將shm_open()、mmap()調用換成了shmget()、shmat()調用sem_post

shmid_ds結構:

#include <sys/shm.h>

// 內核爲每一個共享內存區維護的信息結構
struct shmid_ds{
    struct ipc_perm shm_perm;
    size_t          shm_segsz;
    pid_t           shm_lpid;
    pid_t           shm_cpid;
    shmatt_t        shm_nattch;
    shmat_t         shm_cnattch;
    time_t          shm_atime;
    time_t          shm_dtime;
    time_t          shm_ctime;
};

shmget()函數:

#include <sys/shm.h>

// 建立一個新的共享內存區,或訪問一個已存在的共享內存區
// 成功返回共享內存區標識符,出錯返回-1
int shmget(key_t key, size_t size, int oflag);
// key:System V IPC名字,能夠是ftok()返回值,也能夠是IPC_PRIVATE
// size:指定內存區大小,單位爲字節
//    當建立一個新的共享內存區時,該內存區被初始化爲size字節的0
//    當訪問一個已存在的共享內存區時,size應爲0
// oflag:同shm_open()的oflag參數

shmat()函數:

#include <sys/shm.h>

// 在shmget()打開一個共享內存區後,shmat()將其附接到調用進程的地址空間
// 成功返回映射區起始地址,出錯返回-1
void *shmat(int shmid, const void *shmaddr, int flag);
// shmid: 有shmget()返回的標識符
// shmaddr: 爲空時,系統替調用者選擇指定共享內存區在調用進程內的起始地址
//          非空時,返回地址取決於flag參數
// flag: 指定了SHM_RND時,相應共享內存區附接到由shmaddr參數指定的地址
//       沒有指定SHM_RND,相應共享內存區附接到由shmaddr參數指定的地址向下舍入一個SHMLBA常值
// 默認狀況下,只要調用進程具備某個共享內存區的讀寫權限,它附接到該內存區後就能讀寫該內存區
// flag指定爲SHM_RDONLY時,限定只讀訪問共享內存區

shmdt()函數:

#include <sys/shm.h>

// 斷接某個已附接的共享內存區
// 成功返回0,出錯返回-1
int shmdt(const void *shmaddr);
// shmaddr: 某個已附接的共享內存區的起始地址

shmctl()函數:

#include <sys/shm.h>

// 對共享內存區的各類操做
// 成功返回0,出錯返回-1
int shmctl(int shmid, int cmd, struct shmid_ds *buff);
// shmid: 共享內存區標識符
// cmd:操做命令
// buff:共享內存區信息結構的一個指針

cmd命令:
IPC_RMID:將由shmid指定的共享內存區從系統刪除,並釋放或回收期對應的數據結構
IPC_SET:經過buff指向的結構,設置指定共享內存區的shmid_ds結構的shm_perm.uid shm_perm.gid shm_perm.mode
IPC_STAT: 經過buff返回指定共享內存區當前的shmid_ds結構app

相關文章
相關標籤/搜索