各位看官們,大家好,上一回中咱們說的是SystemV IPC結構概述的例子,這一回咱們說的例子是:使用共享內存進行進程間通信。閒話休提,言歸正轉。讓我們一起talk C栗子吧!
共享內存是SystemV IPC結構這種抽象概念的一種具體對象。就和它的名字一樣,它提供了一段內存空間供不同的進程使用,進程之間可以通過該內存空間傳遞數據,進而實現進程間的通信。
在介紹共享內存的使用方法之前,我們先介紹幾個函數,這些函數都是用來操作共享的內存的。
int shmget(key_t key, size_t size,int shmflag)
該函數用來獲取共享內存,函數返回共享內存的標識符,我們可以通過該標識符使用共享內存;
第一個參數是鍵值,通過它來操作IPC在內核中的結構,也就是共享內存在內核中的結構;(上一回中介紹過)第二個參數是共享內存的容量,單位是byte; 第三個參數是共享內存的權限標記,該權限和文件權限一樣;該函數運行成功時返回共享內存標識符,否則返回-1;在使用該函數的時候,我們需要自己定義一個共享內存的類型,並且計算出該類型的內存空間。共享內存的類型可以依據程序需要來定義,常見的是定義一個結構體類型。
void * shmat(int shm_id, const void *shm_addr,int shmflg)
該函數用來把共享內存連接到進程的地址空間中,這樣進程就可以使用共享內存了;
第一個參數是共享內存的標識符,通過shmget函數可以獲得;第二個參數是一個地址,該地址表示共享內存連接到進程中的位置;第三個參數是一個位標記,只有三個值供使用:SHM_RND,SHM_RDONLY還有0; 該函數運行成功時返回指向共享內存第一個字節的指針,否則返回-1;在使用該函數的時候,第二個參數通常使用一個空指針,空指針表示讓系統自己選擇共享內存連接到進程地址空間的位置,這時第三參數可以使用SHM_RDONLY或者0。如果給第二個參數指定了地址,那麼第三個參數需要使用SHM_RND。
int shmdt(const void *shm_addr)
該函數用來把共享內存從進程的地址空間中分離出來,分離以後進程就不能使用共享內存了;
第一個參數是一個地址,它是共享內存第一個字節的指針,也就是shmat函數的返回值;該函數運行成功時返回0,否則返回-1;
int shmctl(int shm_id, int cmd,struct shmid_ds *buf)
該函數用來把共享內存連接到進程的地址空間中,這樣進程就可以使用共享內存了;
第一個參數是共享內存的標識符,通過shmget函數可以獲得;第二個參數是一個命令,表示對共享內存的操作,只有三個命令供使用:IPC_STAT,IPC_SET和IPC_RMID;第三個參數是一個結構體指針,該結構體中有共享內存的權限和所有者等信息;該函數運行成功時返回0,否則返回-1;我們通常使用該函數刪除共享內存,這時候需要給第二個參數賦值為IPC_RMID,表示刪除共享內存,第三參數可以為空指針。第二個參數的另外兩個命令:
IPC_STAT表示把第三個參數中的內容和共享內存關聯起來; IPC_SET表示把第三個參數中的內容設置為共享內存的值。第三個參數的類型,我們在上一回中提起過,它和SystemV IPC的結構類似,除了必須有的成員外,它還有自己特有的成員。
我從源代碼中找到了第三個參數的類型,詳細的定義如下:(位於linux-4.0.3/include/linux/shm.h文件中)
struct shmid_kernel /* private to the kernel */
{
struct kern_ipc_perm shm_perm;
struct file *shm_file;
unsigned long shm_nattch;
unsigned long shm_segsz;
time_t shm_atim;
time_t shm_dtim;
time_t shm_ctim;
pid_t shm_cprid;
pid_t shm_lprid;
struct user_struct *mlock_user;
/* The task created the shm object. NULL if the task is dead. */
struct task_struct *shm_creator;
struct list_head shm_clist; /* list by creator */
};
各位看官,關於使用共享內存進行進程間通信的例子咱們就說到這裡。欲知後面還有什麼例子,且聽下回分解 。