日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁 > 运维知识 > linux >内容正文

linux

[Linux]共享内存

發(fā)布時(shí)間:2023/11/30 linux 33 豆豆
生活随笔 收集整理的這篇文章主要介紹了 [Linux]共享内存 小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

共享內(nèi)存是UNIX提供的進(jìn)程間通信手段中速度最快的一種,也是最快的IPC形式。為什么是最快的呢,因?yàn)閿?shù)據(jù)不需要在客戶進(jìn)程和服務(wù)器進(jìn)程之間復(fù)制,所以是最快的一種IPC。這是虛存中由多個(gè)進(jìn)程共享的一個(gè)公共內(nèi)存塊。

兩個(gè)不同進(jìn)程A、B共享內(nèi)存的意思是,同一塊物理內(nèi)存被映射到進(jìn)程A、B各自的進(jìn)程地址空間。進(jìn)程A可以即時(shí)看到進(jìn)程B對(duì)共享內(nèi)存中數(shù)據(jù)的更新,反之亦然。

如果服務(wù)器進(jìn)程正在將數(shù)據(jù)放入到共享存儲(chǔ)區(qū),則在它做完這一操作之前,客戶進(jìn)程不應(yīng)當(dāng)去取這些數(shù)據(jù)。通常信號(hào)量用于同步共享存儲(chǔ)訪問。

由于共享內(nèi)存是通過映射到同一塊物理內(nèi)存后進(jìn)行的通信,因此肯定需要映射到內(nèi)存的函數(shù)和解除映射的函數(shù),主要有以下幾種

#define SHMAT 21//空間映射:把上面打開的內(nèi)存區(qū)域連接到用戶的進(jìn)程空間中 #define SHMDT 22//解除映射:將共享內(nèi)存從當(dāng)前進(jìn)程中分離 #define SHMGET 23//創(chuàng)建打開一個(gè)內(nèi)存區(qū)域 #define SHMCTL 24//內(nèi)存區(qū)域的控制:包括初始化和刪除內(nèi)存區(qū)域。

注意:共享內(nèi)存通信本身沒有提供同步機(jī)制,如果同時(shí)被多個(gè)進(jìn)程進(jìn)行映射和寫操作,會(huì)導(dǎo)致破壞該內(nèi)存空間的內(nèi)容。因此在實(shí)際應(yīng)用過程中,需要通過其他的機(jī)制來同步對(duì)共享內(nèi)存的訪問。比如信號(hào)量。

內(nèi)核為每個(gè)共享存儲(chǔ)段維護(hù)著一個(gè)結(jié)構(gòu),該結(jié)構(gòu)至少要為每個(gè)共享存儲(chǔ)段包含以下成員:

struct shmid_ds {struct ipc_perm shm_perm; //ipc結(jié)構(gòu)體size_t shm_segsz; //請(qǐng)求的sizepid_t shm_lpid; //0pid_t shm_cpid; //創(chuàng)建者pidshmatt_t shm_nattch; //當(dāng)前掛載數(shù)time_t shm_atime; //0time_t shm_dtime; //0time_t shm_ctime; //設(shè)置為當(dāng)前時(shí)間 };

1.調(diào)用的第一個(gè)函數(shù)為shmget:

#include<sys/shm.h> int shmget(key_t key,size_t size,int flag); //key是創(chuàng)建共享內(nèi)存id的唯一標(biāo)識(shí)符,size為共享存儲(chǔ)段的長度,以字節(jié)為單位,通常將其向上取為系統(tǒng)頁長的整數(shù)倍。如果不是整頁,則最后剩余部分是不可用的。flag表示相應(yīng)的權(quán)限位。

2.shmctl函數(shù)對(duì)共享內(nèi)存段執(zhí)行多種操作

#include<sys/shm.h> int shmctl(int shmid,int cmd,struct shmid_ds *buf); //IPC_RMID:從系統(tǒng)中刪除該共享存儲(chǔ)段。

3.一旦創(chuàng)建了共享存儲(chǔ)段,進(jìn)程就可調(diào)用shmat將其連接到它的地址空間中。

void *shmat(int shmid,const void* addr,int flag); //返回若成功,返回指向共享存儲(chǔ)段的指針,出錯(cuò)返回-1 //如果成功執(zhí)行,那么內(nèi)核將使與該共享存儲(chǔ)段相關(guān)的shmid_ds結(jié)構(gòu)中的shm_nattch計(jì)數(shù)器值加1;當(dāng)對(duì)共享存儲(chǔ)段的操作已經(jīng)結(jié)束時(shí),則調(diào)用shmat與該段分離。這里并沒有從系統(tǒng)中刪除相關(guān)的數(shù)據(jù)結(jié)構(gòu),該標(biāo)識(shí)符和ipc數(shù)據(jù)結(jié)構(gòu)仍然存在。 int shmdt(const void* addr); //為掛載時(shí)的addr //如果調(diào)用成功,則使與該共享存儲(chǔ)段相關(guān)的shmid_ds結(jié)構(gòu)中的shm_nattch計(jì)數(shù)器值減1

具體代碼實(shí)現(xiàn):

//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; }

運(yùn)行結(jié)果:

總結(jié)

以上是生活随笔為你收集整理的[Linux]共享内存的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。