本章目錄
- 1. 共享記憶體原理
- 2. 創建共享記憶體
- 3. 查看共享記憶體
- 4. 附加共享記憶體到行程
- 5. 代碼驗證介面
- 6. 共享記憶體特性
1. 共享記憶體原理
- 首先在物理記憶體當中創建一塊物理記憶體
- 不同的行程通過頁表映射,將同一塊物理記憶體映射到自己的虛擬地址空間
- 不同的行程,操作行程虛擬地址,通過頁表的映射,就相當于操作同一塊記憶體,從而完成資料的交換
- 具體圖示:

2. 創建共享記憶體
-
創建共享記憶體函式
int shmget(key_t key, size_t size, int shmflg ) ;
key:共享記憶體的識別符號,用來標識一塊共享記憶體,在作業系統當中,共享記憶體的識別符號是不能重復的, 可以直接給32位的16進制數字,
size:共享記憶體的大小
shmflg:IPC_CREAT:如果key標識的共享記憶體不存在,則創建 IPC_EXCL | IPC_CREAT:如果key標識共享記憶體存在,則報錯 權限:按位或8進制數字 0664 (這是共享記憶體的讀寫屬性)回傳值:-1:失敗了
小于0:則成功,回傳的是,共享記憶體的操作句柄,后續是通過操作句柄來進行操作共享記憶體的
3. 查看共享記憶體
- 命令:ipca -m
- 查看介紹

- 共享記憶體的生命周期跟隨作業系統的內核
4. 附加共享記憶體到行程
-
附加共享記憶體到行程相關函式
void *shmat ( int shmid, const void * shmaddr,int shmflg);
shmid:共享記憶體操作句柄,shmget的回傳值
shmaddr:將共享記憶體附加到shmaddr,一般情況下,都不會自己去指定映射到共享區當中的那一段虛擬地址,而是傳遞NULL值,讓作業系統去選擇,
shmflg:標志將共享記憶體附加到行程以后,行程對共享記憶體的讀寫屬性 0:讀寫 SHM_RDONLY :只讀回傳值:[附加成功]:回傳值為附加到虛擬行程中的虛擬地址, [附加失敗]:NULL
-
分離共享記憶體
int shmdt(const void *shmaddr);
shmaddr: 剛附加的時候,回傳共享區的地址 -
共享記憶體操作函式
int fcntl(int fd,int cmd,…)
int shmctl (int shmid,int cmd,struct shmid_ds *buf );
shmid:共享記憶體操作句柄
cmd:IPC_STAT :獲取共享記憶體引數 IPC_SET :設定共享記憶體屬性 IPC_RMID :洗掉共享記憶體struct shmid_ds :共享記憶體屬性對應的結構體 ,洗掉時可以用NULL代替

5. 代碼驗證介面
- 首先是常見一個寫行程,往共享記憶體當中寫入內容
#include <stdio.h>
#include <unistd.h>
#include <string.h>
#include <sys/shm.h>
#define KEY 0x77777777
int main()
{
int shmid = shmget(KEY, 1024, IPC_CREAT | 0664);//創建共享記憶體
if(shmid < 0)
{
perror("shmget");
return 0;
}
//附加到當前的行程
void* addr = shmat(shmid, NULL, 0);
if(addr == NULL)
{
perror("shmat");
return 0;
}
//往共享記憶體寫當中寫
sprintf((char*)addr, "%s", "i am process");
shmdt(addr);
return 0;
}
- 之后再創建一個讀行程,從共享記憶體當中讀
#include <stdio.h>
#include <unistd.h>
#include <sys/shm.h>
#define KEY 0x77777777
int main()
{
int shmid = shmget(KEY, 1024, IPC_CREAT | 0664);
if(shmid < 0)
{
perror("shmget");
return 0;
}
//附加到當前的行程
void* addr = shmat(shmid, NULL, 0);
if(addr == NULL)
{
perror("shmat");
return 0;
}
printf("addr : %s\n", (char*)addr);
shmdt(addr);
return 0;
}
運行結果:

6. 共享記憶體特性
- 共享記憶體讀取資料的時候,是采用拷貝的方式,而不是類似于管道的方式,將資料讀走,也就是資料讀過之后,資料還存在,
- 共享記憶體寫的時候,采用覆寫寫的方式,
- 如果洗掉了一個被行程附加的共享記憶體:
- 當前共享記憶體的識別符號會被改變成0x00000000 ,并且共享記憶體的狀態會變成dest(destroy)
- 我們通過ipsc -m這個命令可以查看到當前被洗掉共享記憶體的資訊,說明被作業系統內核,描述該共享記憶體的結構體沒有被釋放,但是共享記憶體使用的空間已經被釋放了,所以,附加行程如果再次操作共享記憶體,則有崩潰的風險

- 共享記憶體被創建以后,一直存在于內核當中,直到被洗掉或者系統關閉,并且讀取后,內容仍然在其共享記憶體當中,
轉載請註明出處,本文鏈接:https://www.uj5u.com/qukuanlian/282681.html
標籤:區塊鏈
