共享内存
用同一个内存块,实现通信。
共享内存使用方式:
- 在内核中先创建共享内存对象(所用函数:frok,shmget)
- 多个进程附加到这个共享内存对象上(所用函数:shmat,和malloc很像)
- 就可以直接读写这个共享内存了
所用函数:
shmget函数:用来创建共享内存
头文件:
#include<sys/shm.h>
函数:
int shmget(key_t key, size_t size, int shmflg)
参数:
key:这个共享内存段名字,内核中可以同时包含很多共享内存对象,使用不同的 key 区别不同的共享内存对象。
size:共享内存大小
shmflg:由九个权限标志构成,它们的用法和创建文件时使用的mode模式标志是一样的。
返回值:
成功返回一个非负整数,即该共享内存段的标识码;失败返回 -1
int ret=shmget(key,1024,IPC_CREAT | 0666); //IPC_CREAT 存在就打开,不存在就创建 if (ret < 0) { perror("shmget"); return 1; }
ftok函数:得到key,就是shmget函数中的参数 key
key_t ftok(const char *pathname,int proj_id);
返回值:失败返回 -1
//两个参数一样,得到的值永远一样,参数写啥都不是很重要 key_t key=ftok(".",0x1); //当前文件夹,必须有效路径 //0x1 随便给的 if (key == -1) { perror("ftok"); return 1; }
ipcs -m:查看系统中的共享内存
共享内存的生命周期跟随内核。 共享内存一直存在到手动释放或者系统重启。
shmat函数:将共享内存段连接到进程地址空间
void *shmat(int shmid, const void *shmaddr, int shmflg);
参数:
shmid: 共享内存标识,类似文件描述符
shmaddr:指定连接的地址,一般不用添加,都是NULL,也就是让系统说了算。作用连接虚拟地址和物理地址。
shmflg:它的两个可能取值是SHM_RND和SHM_RDONLY,一般默认添 0 都可以,大部分不使用。
返回值:
指针类型,指向共享内存第一个节;失败返回-1
代码实现:
重复的代码放头文件:(核心)
//重复代码,放到 Shm.h 中就好了 #pragma once //防止重复调用 #include<stdio.h> #include<unistd.h> #include<sys/shm.h> //共享内存头文件 static int CreatShm() { //普通函数要加 inline(c++中)/static(C中) 不然会有错误,记住就行,模板就不用 //创建内存 key_t key = ftok(".", 0x1); if (key == -1) { perror("ftok"); return 1; } printf("key= %d\n", key); int ret = shmget(key, 1024, IPC_CREAT | 0666); //IPC_CREAT:存在就打开,不存在就创建,类似文件使用 //返回值类似文件描述符 if (ret < 0) { perror("shmget"); return 1; } printf("ret =%d\n", ret); //共享内存创建之后就要设置权限,也就只有读,写 return ret; }
创建一个共享内存对象:
//creat.c 文件中 #include"Shm.h" //创建一个共享内存对象 int main() { int shmid = CreatShm(); return 0; }
reader.c 文件:读实现
//reader.c 文件 #include"Shm.h" int main() { //从共享内存读数据 //1.创建一个共享内存对象 int shmid = CreatShm(); //2.附加到共享内存上 char* p = (char*)shmat(shmid, NULL, 0); //3.直接使用,就i是使用malloc 内存一样的使用 printf("reader: %s\n", p);// return 0; }
write.c文件:写实现
//write.c 文件 #include"Shm.h" int main() { //从共享内存写数据 //1.创建一个共享内存对象 int shmid = CreatShm(); //2.附加到共享内存对象上 char* p = (char*)shmat(shmid, NULL, 0); //3.直接使用,就i是使用malloc 内存一样的使用 strcpy(p, "hehe\n"); return 0; }
Makefile文件:
//Makefile .PHONY:all all : reader writer //一个make生成所有的 reader : reader.c gcc $^ -o $@ writer : writer.c gcc $^ -o $@ .PHONY:clean clean : rm reader writer
运行自然先写,再读。
解除共享内存:
可以用函数 shmdt函数 ,不释放也无所谓没什么影响。