共享内存允许两个或者多个进程共享给定的存储区域
共享内存的特点
1.共享内存是进程间共享数据的一种最快的方法
一个进程向共享的内存区域写入了数据,共享这个内存区域的所有进程就可以立刻看到其中的内容
2.使用共享内存要注意的是多个进程之间对一个给定存储区访问的互斥
若一个进程正在向共享内存区写数据,则在它做完这一步 *** 作前,别的进程不应当去读,写这些数据。
上面图片讲解:
左右两边每一个进程在创建的时候,都会给它分配4G的虚拟内存,所以左右两边的空间叫做虚拟内存,而中间的是物理内存,也就是内存条上的存储区域,这两个进程的前三个空间,4G虚拟内存分为3G的用户空间和1G的内核空间,每一个进程的用户空间是私有的,所以它们最终到达物理内存对应的区域是不相同的,所以说进程A和进程B的用户空间是没有办法进行沟通的,而另外空间,它俩映射出来的都是物理空间同一块区域,所以假设进程a在区域写,刚好b就能读,共享内存就相当于可以把物理地址先交给用户,由我的用户进程对其地址进行 *** 作,就是对物理地址进行 *** 作。
总结:共享内存是进程间通信方式中效率最高的
原因在于进程是直接在物理内存上进行 *** 作,将物理地址映射到用户进程这,所以只要对其地址进行 *** 作,就是直接对物理地址 *** 作。所以快
获取一个共享内存标识符
#include功能#include int shmget(key_t key, size_t size, int shmflg);
创建一个共享内存
参数key: 键值,唯一的键值确定唯一的共享内存
size: 创建的共享内存的大小
shmflg: 共享内存的访问权限
IPC_CREAT: 创建这个共享内存
IPC_EXCL: 如果已经存在则返回失败
一般为IPC_CREAT | 0666
成功 返回共享内存的id
失败: 返回-1
查看共享内存
ipcs -m
删除共享内存
ipcrm -m shmid
#include#include #include #include #include int main() { key_t key; if((key = ftok(".", 100)) == -1) { perror("fail to ftok"); exit(1); } int shmid; //使用shmget创建一个共享内存 if((shmid = shmget(key, 500, IPC_CREAT | 0666)) == -1) { perror("fail to shmget"); exit(1); } printf("shmid = %dn", shmid); system("ipcs -m"); return 0; } ~
共享内存的映射
就是将物理内存所对应的地址,映射到用户空间的数据段上,只要映射过来之后,就可以获取映射的地址,就可以对地址 *** 作也就是对物理内存 *** 作。
#include#include void *shmat(int shmid, const void* shmaddr, int shmflg);
功能
映射共享内存
参数
shmid: 共享内存的id
shmaddr: 映射的地址,设置为NULL为系统自动分配
shmflg:标志位
0:共享内存具有可读可写权限
SHM_RDONLY: 只读
返回值
成功:映射的地址
失败:-1
shmat函数使用的时候第二个和第三个参数一般设为NULL和0,即系统自动指定共享内存地址,并且共享内存可读可写
解除共享内存映射(detach)
#include#include int shmdt(const void* shmaddr);
功能:
将共享内存和当前进程分离(仅仅是断开联系并不删除共享内存)
参数:
shmaddr: 共享内存映射地址
返回值:
成功返回0,失败返回-1
案例:
write.c
#include#include #include #include #include #include typedef struct{ int a; char b; }MSG; int main(int argc, char const *argv[]) { //使用ftok函数获取键值 key_t mykey; if((mykey = ftok(".", 100)) == -1) { perror("fail to ftok"); exit(1); } //通过shmget函数创建或者打开一个共享内存,返回一个共享内存的标识符 int shmid; if((shmid = shmget(mykey, 500, IPC_CREAT | 0666)) == -1) { perror("fail to shmget"); exit(1); } system("ipcs -m"); //使用shmat函数映射共享内存的地址 //char *text; MSG *text; if((text = shmat(shmid, NULL, 0)) == (void *)-1) { perror("fail to shmat"); exit(1); } //通过shmat的返回值对共享内存 *** 作 //strcpy(text, "hello world"); text->a = 100; text->b = 'w'; // *** 作完毕后要接触共享内存的映射 if(shmdt(text) == -1) { perror("fail to shmdt"); exit(1); } system("ipcs -m"); return 0; }
read.c
#include#include #include #include #include typedef struct{ int a; char b; }MSG; int main(int argc, char const *argv[]) { //使用ftok函数获取键值 key_t mykey; if((mykey = ftok(".", 100)) == -1) { perror("fail to ftok"); exit(1); } //通过shmget函数创建或者打开一个共享内存,返回一个共享内存的标识符 int shmid; if((shmid = shmget(mykey, 500, IPC_CREAT | 0666)) == -1) { perror("fail to shmget"); exit(1); } system("ipcs -m"); //映射共享内存的地址 //char *text; MSG *text; if((text = shmat(shmid, NULL, 0)) == (void *)-1) { perror("fail to shmat"); exit(1); } //获取共享内存中的数据 //printf("text = %sn", text); printf("a = %d, b = %cn", text->a, text->b); //解除共享内存映射 if(shmdt(text) == -1) { perror("fail to shmdt"); exit(1); } system("ipcs -m"); return 0; }
写的结果
读的结果
共享内存的控制
#include#include int shmctl(int shmid, int cmd, struct shmid_ds *buf);
功能
设置或者获取共享内存你的属性
参数
shmid: 共享内存的id
cmd:执行 *** 作的命令
IPC_STAT 获取共享内存的属性
IPC_SET 设置共享内存的属性
IPC_RMID 删除共享内存
shmid_ds 共享内存的属性结构体
返回值
成功: 返回0
失败: -1
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)