共享記憶體是執行在同一臺機器上的程序間通訊最快的方式,因為資料不需要在不同的程序間複製。通常由乙個程序建立一塊共享記憶體區,其餘程序對這塊記憶體區進行讀寫。共享記憶體往往與其它通訊機制,如訊號量結合使用,來達到程序間的同步及互斥。
首先要用的函式是shmget,它獲得乙個共享儲存識別符號。
#i nclude
#i nclude
#i nclude
int shmget(key_t key, int size, int flag);
這個函式有點類似大家熟悉的malloc函式,系統按照請求分配size大小的記憶體用作共享記憶體。linux系統核心中每個ipc結構都有的乙個非負整數的識別符號,這樣對乙個訊息佇列傳送訊息時只要引用識別符號就可以了。這個識別符號是核心由ipc結構的關鍵字得到的,這個關鍵字,就是上面第乙個函式的key。資料型別key_t是在標頭檔案sys/types.h中定義的,它是乙個長整形的資料。在我們後面的章節中,還會碰到這個關鍵字。
當共享記憶體建立後,其餘程序可以呼叫shmat()將其連線到自身的位址空間中。
void *shmat(int shmid, void *addr, int flag);
shmid為shmget函式返回的共享儲存識別符號,addr和flag引數決定了以什麼方式來確定連線的位址,函式的返回值即是該程序資料段所連線的實際位址,程序可以對此程序進行讀寫操作。
使用共享儲存來實現程序間通訊的注意點是對資料訪問的同步,必須確保當乙個程序去讀取資料時,它所想要的資料已經寫好了。通常,訊號量被要來實現對共享儲存資料訪問的同步,另外,可以通過使用shmctl函式設定共享儲存記憶體的某些標誌位如shm_lock、shm_unlock等來實現。
共享記憶體機制使得兩個不相關程序可以讀取和修改同一段記憶體從而實現資料共享。主要函式定義:
#include
void *shmat(int shm_id, const void *shm_addr, int shm***);
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 shmflag);
c**
/*server.c:向共享記憶體中寫入people*/
#include
#include
#include
#include
int main()
;
int semid;
int shmid;
key_t semkey;
key_t shmkey;
semkey=ftok("server.c",0);
shmkey=ftok("client.c",0);
/*建立共享記憶體和訊號量的ipc*/
semid=semget(semkey,1,0666|ipc_creat);
if(semid==-1)
printf("creat sem is fail\n");
shmid=shmget(shmkey,1024,0666|ipc_creat);
if(shmid==-1)
printf("creat shm is fail\n");
/*設定訊號量的初始值,就是資源個數*/
union semunsem_u;
sem_u.val=1;
semctl(semid,0,setval,sem_u);
/*將共享記憶體對映到當前程序的位址中,之後直接對程序中的位址addr操作就是對共享記憶體操作*/
struct people * addr;
addr=(struct people*)shmat(shmid,0,0);
if(addr==(struct people*)-1)
printf("shm shmat is fail\n");
/*訊號量的p操作*/
void p()
/*訊號量的v操作*/
void v()
/*向共享記憶體寫入資料*/
p();
strcpy((*addr).name,"xiaoming");
/*注意:①此處只能給指標指向的位址直接賦值,不能在定義乙個 struct people people_1;addr=&people_1;因為addr在addr=(struct people*)shmat(shmid,0,0);時,已經由系統自動分配了乙個位址,這個位址與共享記憶體相關聯,所以不能改變這個指標的指向,否則他將不指向共享記憶體,無法完成通訊了。
注意:②給字元陣列賦值的方法。剛才太虎了。。*/
(*addr).age=10;
v();
/*將共享記憶體與當前程序斷開*/
if(shmdt(addr)==-1)
printf("shmdt is fail\n");
}
c**
/*client.c:從共享記憶體中讀出people*/
#include
#include
#include
#include
int main()
;
/*讀取共享記憶體和訊號量的ipc*/
semid=semget(semkey,0,0666);
if(semid==-1)
printf("creat sem is fail\n");
shmid=shmget(shmkey,0,0666);
if(shmid==-1)
printf("creat shm is fail\n");
/*將共享記憶體對映到當前程序的位址中,之後直接對程序中的位址addr操作就是對共享記憶體操作*/
struct people * addr;
addr=(struct people*)shmat(shmid,0,0);
if(addr==(struct people*)-1)
printf("shm shmat is fail\n");
/*訊號量的p操作*/
void p()
/*訊號量的v操作*/
void v()
/*從共享記憶體讀出資料*/
p();
printf("name:%s\n",addr->name);
printf("age:%d\n",addr->age);
v();
/*將共享記憶體與當前程序斷開*/
if(shmdt(addr)==-1)
printf("shmdt is fail\n");
/*ipc必須顯示刪除。否則會一直留存在系統中*/
if(semctl(semid,0,ipc_rmid,0)==-1)
printf("semctl delete error\n");
if(shmctl(shmid,ipc_rmid,null)==-1)
printf("shmctl delete error\n");
}
Linux程序間共享記憶體通訊
使用共享記憶體基本分四個步驟 獲得共享記憶體 shmget 對映共享記憶體shmat 解除對映shmdt 刪除共享記憶體shmctl 於是自己在網上找來了乙個例子看了下,並且用虛擬機器單獨跑了下共享記憶體的經典例程看了下,才知道了自己的問題出現 了 發現有時候只要自己親自將程式一步一步的去測,才知道...
Linux程序間通訊 共享記憶體
之前提到了程序間通訊的管道,訊息佇列,訊號量,然後其中訊號量是pv操作,操控的是乙個共享資源。在我們提到的ipc模組中,訊息佇列針對的是資料單元的資訊傳送,管道不屬於system v ipc的部分,所以按照乙個作業系統的整體來說,他應該也有著乙個關於位元組流的訊息傳輸,並且要比之前都要快,還要跟我們...
Linux程序間通訊 共享記憶體
一 共享記憶體 1 共享記憶體的概念 顧名思義,共享記憶體就是允許兩個不相關的程序訪問同乙個邏輯記憶體。共享記憶體是在兩個正在執行的程序之間共享和傳遞資料的一種非常有效的方式。不同程序之間共享的記憶體通常安排為同一段物理記憶體。程序可以將同一段共享記憶體連線到它們自己的位址空間中,所有程序都可以訪問...