[Linux]共享内存
生活随笔
收集整理的這篇文章主要介紹了
[Linux]共享内存
小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
共享內存是UNIX提供的進程間通信手段中速度最快的一種,也是最快的IPC形式。為什么是最快的呢,因為數據不需要在客戶進程和服務器進程之間復制,所以是最快的一種IPC。這是虛存中由多個進程共享的一個公共內存塊。
兩個不同進程A、B共享內存的意思是,同一塊物理內存被映射到進程A、B各自的進程地址空間。進程A可以即時看到進程B對共享內存中數據的更新,反之亦然。
如果服務器進程正在將數據放入到共享存儲區,則在它做完這一操作之前,客戶進程不應當去取這些數據。通常信號量用于同步共享存儲訪問。
由于共享內存是通過映射到同一塊物理內存后進行的通信,因此肯定需要映射到內存的函數和解除映射的函數,主要有以下幾種
#define SHMAT 21//空間映射:把上面打開的內存區域連接到用戶的進程空間中 #define SHMDT 22//解除映射:將共享內存從當前進程中分離 #define SHMGET 23//創建打開一個內存區域 #define SHMCTL 24//內存區域的控制:包括初始化和刪除內存區域。注意:共享內存通信本身沒有提供同步機制,如果同時被多個進程進行映射和寫操作,會導致破壞該內存空間的內容。因此在實際應用過程中,需要通過其他的機制來同步對共享內存的訪問。比如信號量。
內核為每個共享存儲段維護著一個結構,該結構至少要為每個共享存儲段包含以下成員:
struct shmid_ds {struct ipc_perm shm_perm; //ipc結構體size_t shm_segsz; //請求的sizepid_t shm_lpid; //0pid_t shm_cpid; //創建者pidshmatt_t shm_nattch; //當前掛載數time_t shm_atime; //0time_t shm_dtime; //0time_t shm_ctime; //設置為當前時間 };1.調用的第一個函數為shmget:
#include<sys/shm.h> int shmget(key_t key,size_t size,int flag); //key是創建共享內存id的唯一標識符,size為共享存儲段的長度,以字節為單位,通常將其向上取為系統頁長的整數倍。如果不是整頁,則最后剩余部分是不可用的。flag表示相應的權限位。2.shmctl函數對共享內存段執行多種操作
#include<sys/shm.h> int shmctl(int shmid,int cmd,struct shmid_ds *buf); //IPC_RMID:從系統中刪除該共享存儲段。3.一旦創建了共享存儲段,進程就可調用shmat將其連接到它的地址空間中。
void *shmat(int shmid,const void* addr,int flag); //返回若成功,返回指向共享存儲段的指針,出錯返回-1 //如果成功執行,那么內核將使與該共享存儲段相關的shmid_ds結構中的shm_nattch計數器值加1;當對共享存儲段的操作已經結束時,則調用shmat與該段分離。這里并沒有從系統中刪除相關的數據結構,該標識符和ipc數據結構仍然存在。 int shmdt(const void* addr); //為掛載時的addr //如果調用成功,則使與該共享存儲段相關的shmid_ds結構中的shm_nattch計數器值減1具體代碼實現:
//comm.h #ifndef _COMM_H_ #define _COMM_H_ #include<stdio.h> #include<sys/types.h> #include<sys/ipc.h> #include<sys/shm.h>#define PATHNAME "." #define PROJ_ID 0X6667int CreateShm(int size); int GetShm(int size);int destroyShm(int shmid);#endif //_COMM_H_ //comm.c #include"comm.h"int CommShm(int size,int flags) {key_t key = ftok(PATHNAME,PROJ_ID);if(key < 0){perror("ftok");return -1;}int shmid = shmget(key,size,flags); if(shmid < 0){perror("shmget");return -2;}return shmid; }int CreateShm(int size) {return CommShm(size,IPC_CREAT|IPC_EXCL|0666); } int GetShm(int size) {return CommShm(size,IPC_CREAT); } int destroyShm(int shmid) {if(shmctl(shmid,IPC_RMID,NULL) < 0){perror("shmctl");return -1;}return 0; } //server.c #include"comm.h"int main() {int shmid = CreateShm(4096); // printf("hello server!\n");char *addr = shmat(shmid,NULL,0);if(addr == NULL){return 1;}int i = 0;char s = 'a';while(1){addr[i] = s;s++;}addr[i] = 0;sleep(4);shmdt(addr);printf("shm quit!\n");return 0; } //client.c #include"comm.h"int main() {int shmid = GetShm(4096);//printf("hello client!\n");char *addr = shmat(shmid,NULL,0);if(addr == NULL)return 2;printf("%s",addr);sleep(10);shmdt(addr); printf("shm quit!\n");return 0; }運行結果:
總結
以上是生活随笔為你收集整理的[Linux]共享内存的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: DNF开启古老的英雄袖珍罐要多少金币?
- 下一篇: 到底如何深入VIM 财富值2