阐述linux IPC(五岁以下儿童):system V共享内存
生活随笔
收集整理的這篇文章主要介紹了
阐述linux IPC(五岁以下儿童):system V共享内存
小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
【版權聲明:尊重原創。轉載請保留源:blog.csdn.net/shallnet 要么 .../gentleliu,文章學習交流,不用于商業用途】
? ? ? ? system V共享內存和posix共享內存類似,system V共享內存是調用shmget函數和shamat函數。 ??
? ? ? ? shmget函數創建共享內存區,或者訪問一個存在的內存區,類似系統調用共享內存的open和posix共享內存shm_open函數。
? ? ? ? ftok函數原型為:key_t ftok(const char *pathname, int proj_id); 參數pathname為文件絕對路徑名,proj_id為一個整型標識符。該函數將一個已存在的的路徑名和一個整型標識符轉化成一個key_t值(返回值),稱為IPC鍵。
? ? ? ? size:創建新的共享內存大小,當創建一片新的共享內存時。該值為不為0的參數。假設是讀取一片共享內存,該值能夠為0。
? ? ? ? shmaddr: 連接到調用進程地址空間的地址,假設該參數為NULL,系統選擇一個合適地址。假設shmaddr非空而且shmflg指定了選項SHM_RND,那么對應的共享內存鏈接到由shmaddr參數指定的地址向下舍入一個SHMLAB常值。假設shmaddr非空而且shmflg未指定SHM_RND,共享內存地址鏈接到shmaddr參數指定的地址。
? ? ? ? shmflg:能夠指定SHM_RND和SHM_RDONLY(僅僅讀),假設指定SHM_RDONLY選項。那么調用進程對該片共享內存僅僅有讀權限,否則,進程對該片內存將有讀寫權限。
? ? ? ? 函數shmdt不會刪除指定的共享內存,它僅僅是斷開和該片共享內存的鏈接而已。當一個進程終止后。該進程鏈接的共享內存將自己主動斷開。
? ? ? ? shmat函數成功返回當前進程共享內存地址,失敗返回(void *)-1;shmdt成功返回0。失敗返回-1;
? ? ? ? 刪除共享內存須要函數shmctl調用IPC_RMID命令來完畢。
#include <sys/ipc.h>#include <sys/shm.h>int shmctl(int shmid, int cmd, struct shmid_ds *buf);
? ? ? ? shmid:共享內存區標識。
? ? ? ? cmd:對共享內存的操作命令,命令IPC_RMID銷毀(destroy)一片共享內存,銷毀之后全部shmat。shmdt,shmctl對該片內存操作都將失效。銷毀該共享內存要等到該共享內存引用計數變為0才進行。IPC_SET命令設置shmid_ds結構成員;IPC_STAT返回當前共享內存結構。其余命令查看man手冊。
? ? ? ? buf:為指向shmid_ds數據結構;
system V 共享內存演示樣例:
server process:
int sln_shm_get(char *shm_file, void **mem, int mem_len) {int shmid;key_t key;if (NULL == fopen(shm_file, "w+")) {printf("fopen: %s\n", strerror(errno));return -1;}key = ftok(shm_file, 0);if (key < 0) {printf("ftok: %s\n", strerror(errno));return -1;}shmid = shmget(key, mem_len, IPC_CREAT);if (shmid < 0) {printf("shmget: %s\n", strerror(errno));return -1;}*mem = (void *)shmat(shmid, NULL, 0);if ((void *)-1 == *mem) {printf("shmat: %s\n", strerror(errno));return -1;}return shmid; }int main(int argc, const char *argv[]) {char *shm_file = NULL;char *shm_buf = NULL;int shmid;shmid = sln_shm_get(SHM_IPC_FILENAME, (void **)&shm_buf, SHM_IPC_MAX_LEN);if (shmid < 0) {return -1;}snprintf(shm_buf, SHM_IPC_MAX_LEN, "Hello system V shaare memory IPC! this is write by server.");sleep(15); printf("System V server delete share memory segment!\n");//shmdt(shm_buf);shmctl(shmid, IPC_RMID, NULL); //server在15秒之后destroy該片共享內存。此時客戶進程將獲取不到共享內存的內容return 0; }
執行時,首先執行server process,使用命令ipcs能夠查看當前系統共享內存:
# ipcs ------ Message Queues -------- key msqid owner perms used-bytes messages ------ Shared Memory Segments -------- key shmid owner perms bytes nattch status 0x0010a797 131072 root 0 4096 1 ------ Semaphore Arrays -------- key semid owner perms nsems
能夠看到存在一個共享內存區,當中key為:0x0010a797 ,共享內存ID為:131072?
# ./client ipc client get: Hello system V shaare memory IPC! this is write by server. #
當server進程destroy共享內存之后,再反復上面步驟,
# ipcs ------ Message Queues -------- key msqid owner perms used-bytes messages ------ Shared Memory Segments -------- key shmid owner perms bytes nattch status ------ Semaphore Arrays -------- key semid owner perms nsems 此時共享內存已經不在了,但文件依舊存在。
此時client已經不能獲取之前共享內存內容了。
另外,ipcrm命令能夠在命令行上刪除指定共享內存區。
通過讀取文件/proc/sys/kernel/shmmax能夠獲取系統所支持共享內存最大值,
# cat /proc/sys/kernel/shmmax 33554432 #
能夠看到我眼下系統支持最大個共享內存值為:32M。
通過上演示樣例能夠看到system V共享內存和posix共享內存類似,只是posix共享內存的大小能夠隨時通過ftruncate改變,而system V 的共享內存大小在shmget時就已經確定下來了。
? ? ? ? system V共享內存和posix共享內存類似,system V共享內存是調用shmget函數和shamat函數。 ??
? ? ? ? shmget函數創建共享內存區,或者訪問一個存在的內存區,類似系統調用共享內存的open和posix共享內存shm_open函數。
shmget函數原型為:
? ? ? ? ftok函數原型為:key_t ftok(const char *pathname, int proj_id); 參數pathname為文件絕對路徑名,proj_id為一個整型標識符。該函數將一個已存在的的路徑名和一個整型標識符轉化成一個key_t值(返回值),稱為IPC鍵。
? ? ? ? size:創建新的共享內存大小,當創建一片新的共享內存時。該值為不為0的參數。假設是讀取一片共享內存,該值能夠為0。
? ? ? ? shmflg:讀寫權限值組合。
IPC_CREAT(創建新的共享內存)或IPC_CREAT|IPC_EXCL(當將要創建的共享內存已經存在時,再試圖創建將返回EEXIST)。
事實上IPC_CREAT和IPC_EXCL的組合和open函數的O_CREAT和O_EXCL組合類似。
? ? ? ? 函數返回共享內存區的標識。
shmxxx函數操作共享內存將使用該函數返回值。
該函數類似posix共享內存shm_open函數功能。
? ? ? ? 當shmget創建或打開一個共享內存區后。須要使用函數shmat來將該片共享內存連接到當前進程空間中來,當某一進程使用完共享內存后,使用函數shmdt斷開和共享內存的鏈接。
? ? ? ? shmaddr: 連接到調用進程地址空間的地址,假設該參數為NULL,系統選擇一個合適地址。假設shmaddr非空而且shmflg指定了選項SHM_RND,那么對應的共享內存鏈接到由shmaddr參數指定的地址向下舍入一個SHMLAB常值。假設shmaddr非空而且shmflg未指定SHM_RND,共享內存地址鏈接到shmaddr參數指定的地址。
? ? ? ? shmflg:能夠指定SHM_RND和SHM_RDONLY(僅僅讀),假設指定SHM_RDONLY選項。那么調用進程對該片共享內存僅僅有讀權限,否則,進程對該片內存將有讀寫權限。
? ? ? ? 函數shmdt不會刪除指定的共享內存,它僅僅是斷開和該片共享內存的鏈接而已。當一個進程終止后。該進程鏈接的共享內存將自己主動斷開。
? ? ? ? shmat函數成功返回當前進程共享內存地址,失敗返回(void *)-1;shmdt成功返回0。失敗返回-1;
? ? ? ? 刪除共享內存須要函數shmctl調用IPC_RMID命令來完畢。
#include <sys/ipc.h>#include <sys/shm.h>int shmctl(int shmid, int cmd, struct shmid_ds *buf);
? ? ? ? shmid:共享內存區標識。
? ? ? ? cmd:對共享內存的操作命令,命令IPC_RMID銷毀(destroy)一片共享內存,銷毀之后全部shmat。shmdt,shmctl對該片內存操作都將失效。銷毀該共享內存要等到該共享內存引用計數變為0才進行。IPC_SET命令設置shmid_ds結構成員;IPC_STAT返回當前共享內存結構。其余命令查看man手冊。
? ? ? ? buf:為指向shmid_ds數據結構;
system V 共享內存演示樣例:
server process:
int sln_shm_get(char *shm_file, void **mem, int mem_len) {int shmid;key_t key;if (NULL == fopen(shm_file, "w+")) {printf("fopen: %s\n", strerror(errno));return -1;}key = ftok(shm_file, 0);if (key < 0) {printf("ftok: %s\n", strerror(errno));return -1;}shmid = shmget(key, mem_len, IPC_CREAT);if (shmid < 0) {printf("shmget: %s\n", strerror(errno));return -1;}*mem = (void *)shmat(shmid, NULL, 0);if ((void *)-1 == *mem) {printf("shmat: %s\n", strerror(errno));return -1;}return shmid; }int main(int argc, const char *argv[]) {char *shm_file = NULL;char *shm_buf = NULL;int shmid;shmid = sln_shm_get(SHM_IPC_FILENAME, (void **)&shm_buf, SHM_IPC_MAX_LEN);if (shmid < 0) {return -1;}snprintf(shm_buf, SHM_IPC_MAX_LEN, "Hello system V shaare memory IPC! this is write by server.");sleep(15); printf("System V server delete share memory segment!\n");//shmdt(shm_buf);shmctl(shmid, IPC_RMID, NULL); //server在15秒之后destroy該片共享內存。此時客戶進程將獲取不到共享內存的內容return 0; }
client process:
執行時,首先執行server process,使用命令ipcs能夠查看當前系統共享內存:
# ipcs ------ Message Queues -------- key msqid owner perms used-bytes messages ------ Shared Memory Segments -------- key shmid owner perms bytes nattch status 0x0010a797 131072 root 0 4096 1 ------ Semaphore Arrays -------- key semid owner perms nsems
能夠看到存在一個共享內存區,當中key為:0x0010a797 ,共享內存ID為:131072?
# ./client ipc client get: Hello system V shaare memory IPC! this is write by server. #
當server進程destroy共享內存之后,再反復上面步驟,
# ipcs ------ Message Queues -------- key msqid owner perms used-bytes messages ------ Shared Memory Segments -------- key shmid owner perms bytes nattch status ------ Semaphore Arrays -------- key semid owner perms nsems 此時共享內存已經不在了,但文件依舊存在。
# ./client ipc client get: #
此時client已經不能獲取之前共享內存內容了。
另外,ipcrm命令能夠在命令行上刪除指定共享內存區。
通過讀取文件/proc/sys/kernel/shmmax能夠獲取系統所支持共享內存最大值,
# cat /proc/sys/kernel/shmmax 33554432 #
能夠看到我眼下系統支持最大個共享內存值為:32M。
通過上演示樣例能夠看到system V共享內存和posix共享內存類似,只是posix共享內存的大小能夠隨時通過ftruncate改變,而system V 的共享內存大小在shmget時就已經確定下來了。
相同的,system V共享內存大多數時候也須要在多進程之間同步,system V 能夠使用自己的信號量來實現,具體細節將在后面同步相關專欄具體解說。
本節源代碼下載:
版權聲明:本文博客原創文章,博客,未經同意,不得轉載。
轉載于:https://www.cnblogs.com/mengfanrong/p/4712512.html
總結
以上是生活随笔為你收集整理的阐述linux IPC(五岁以下儿童):system V共享内存的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 多点电容触摸屏实验
- 下一篇: Linux CAN 驱动实验