二、共享記憶體的使用
三、共享記憶體的demo
四、共享記憶體總結
顧名思義,共享記憶體就是允許多個不相關的程序訪問同乙個邏輯記憶體。共享記憶體是在兩個正在執行的程序之間共享和傳遞資料的一種非常有效的方式。不同程序之間共享的記憶體通常安排為同一段物理記憶體。程序可以將同一段共享記憶體連線到它們自己的位址空間中,所有程序都可以訪問共享記憶體中的位址,就好像它們是由用c語言函式malloc分配的記憶體一樣。而如果某個程序向共享記憶體寫入資料,所做的改動將立即影響到可以訪問同一段共享記憶體的任何其他程序。
在linux中,每個程序都有屬於自己的程序控制塊(pcb)和位址空間(addr space),並且都有乙個與之對應的頁表,負責將程序的虛擬位址與實體地址進行對映,通過記憶體管理單元(mmu)進行管理。兩個不同的虛擬位址通過頁表對映到物理空間的同一區域,它們所指向的這塊區域即共享記憶體。
當兩個程序通過頁表將虛擬位址對映到實體地址時,在實體地址中有一塊共同的記憶體區,即共享記憶體,這塊記憶體可以被兩個程序同時看到。這樣當乙個程序修改共享記憶體的資料時,另乙個程序訪問共享記憶體時就會得到新的資料。
在乙個linux伺服器上,共享記憶體的總體大小是有限制的,這個大小通過shmmax引數來定義(以位元組為單位),您可以通過執行以下命令來確定 shmmax 的值:
# cat /proc/sys/kernel/shmmax
shmmax 的預設值是 32mb 。一般使用下列方法之一種將 shmmax 引數設為 2gb :
sysctl -w kernel.shmmax=2147483648
當首次建立共享記憶體段時,它並不能被任何程序所訪問。為了使共享記憶體區可以被訪問,則必須通過shmat函式將其附加( attach )到自己的程序空間中,這樣程序就與共享記憶體建立了連線。
這樣掛載乙個共享記憶體如果是一次呼叫是沒有問題的,但是乙個程序是可以對同乙個共享記憶體多次 shmat進行掛載的,物理記憶體是指向同一塊,如果shmaddr為null,則每次返回的線性位址空間都不同。而且指向這塊共享記憶體的引用計數會增加,也就是程序多塊線性空間會指向同一塊實體地址。這樣,如果之前掛載過這塊共享記憶體的程序的線性位址沒有被shmdt掉,即申請的線性位址都沒有釋放,就會一直消耗程序的虛擬記憶體空間,很有可能會最後導致程序線性空間被使用完而導致下次shmat或者其他操作失敗。
可以通過判斷需要申請的共享記憶體指標是否為空來標識是否是第一次掛載共享記憶體,若是則使用進行掛載,若不是則退出。
void
* ptr =
null;.
..if(
null
!= ptr)
return
; ptr =
shmat
(shmid,ptr,
0666
);
1.呼叫函式shmget()建立乙個新共享記憶體段或者取得乙個既有的共享記憶體段的識別符號;
3. 為了引用共享記憶體,程式需要使用由shmat()函式返回的addr值,它是乙個指向程序的虛擬位址空間中該共享記憶體段起點的指標;
4. 呼叫函式shmdt()分離共享記憶體段,呼叫之後,程序無法再引用這段共享記憶體。
5. 呼叫函式shmctl()刪除共享記憶體段。只有乙個程序需要執行這一步。
#include
#include
intshmget
(key_t key, size_t size,
int shm***)
;
#include
#include
void
*shmat
(int shm_id,
const
void
*shm_addr,
int shm***)
;
返回值:成功:返回乙個指向共享記憶體第乙個位元組的指標。失敗:返回-1。
#include
#include
intshmdt
(const
void
*shmaddr)
;
返回值:成功:返回0。失敗:返回-1。
#include
intshmctl
(int shm_id,
int command,
struct shmid_ds *buf)
;
buf:乙個結構指標,它指向共享記憶體模式和訪問許可權的結構。
struct shmid_ds
;
// shmwrite.cpp
#include
#include
#include
#include
#include
#include
#include
#include
#include
#define buffer 4096
#define perm s_irusr|s_iwusr
intmain
(int argc,
char
*argv)
// 將共享記憶體段載入到呼叫程序的虛擬位址空間中
char
* shmaddr =
(char*)
shmat
(shmid,
null,0
);if(shmaddr ==
(void*)
-1)// 從標準輸入讀資料
fgets
(shmaddr,
100,
stdin);
// 分離共享記憶體段if(
shmdt
(shmaddr)==-
1)sleep(10
);// 睡眠十秒後共享記憶體失效
// 刪除這塊共享記憶體if(
shmctl
(shmid, ipc_rmid,
null)==
-1)return0;
}
// shmread.cpp
#include
#include
#include
#include
#include
#include
#include
#include
#include
#define buffer 4096
#define perm s_irusr|s_iwusr
intmain
(int argc,
char
**argv)
char
* shmaddr =
(char*)
shmat
(shmid,
null,0
);if(shmaddr ==
(void*)
-1)// 輸出從另乙個程序傳過來的資料
printf
("%s\n"
, shmaddr);if
(shmdt
(shmaddr)==-
1)return0;
}
共享記憶體就是對映一段能被其他程序所訪問的記憶體,這段共享記憶體由乙個程序建立,但多個程序都可以訪問。共享記憶體是最快的ipc(程序間通訊)方式,它是針對其它程序間通訊方式執行效率低而專門設計的。它往往與其他通訊機制,如訊號量,配合使用,來實現程序間的同步與通訊。
【優點】:
【缺點】:
參考:
程序間通訊之共享記憶體
此程式實現兩個普通程序間通過共享記憶體來進行通訊,共享記憶體能夠進行大資料量的通訊,這一點事訊息佇列無法比擬的。在這裡同時使用了訊號量來保證兩個程序間的讀寫同步。傳送端源 include include include include include include include include ...
程序間通訊之共享記憶體
1.概念 共享記憶體就是多個程序的位址空間對映到同乙個物理記憶體,多個程序都能看到這塊物理記憶體,共享記憶體可以提供給伺服器程序和客戶程序之間進行通訊,不需要進行資料的複製,所以速度最快。2.共享記憶體操作需要的函式 1 我們需要利用ftok函式生成key識別符號。key t ftok const ...
程序間通訊之共享記憶體
ipc物件這個概念需要理解,因為好多書或者料就直接說ipc就是共享記憶體 訊息佇列 訊號燈集,其實ipc是一種機制,這種機制提供了程序間通訊的通道,那麼為什麼加個system v呢,那是因為在system v 系統的四個版本中提出的程序通訊的ipc這種機制。所以叫做system v ipc。目前li...