基本参考 《Unix环境高级编程》第14.9节共享内存来学习。
参考blog:https://blog.csdn.net/weixin_45794138/article/details/121256996
讲shmget(key,size, flag)函数时,书上大概意识是说,
想访问已有的shm时,key不应与IPC_CREATE 同时指定。
已有此key的shm且size满足要求(已有shm的size ≥ 函数中指定的size)时,直接返回已有的shmid。
若size不满足,则失败返回-1
若未有此key的shm,则使用 key 和 size 创建新的IPC结构,并返回shmid;创建失败则返回-1.
int shmid = shmget(key, SHM_SIZE, IPC_CREAT|IPC_EXCL|0666); //强制创建新的,且指定访问权bits位 int shmid = shmget(key, SHM_SIZE, 0); //强制使用已有的,且满足 size >= SHM_SIZE, 否则失败返回-1 int shmid = shmget(key, SHM_SIZE, IPC_CREAT); //若无此key的shm,则创建新的shmid并返回,创建失败返回-1; //若已有此key的shm且size满足要求,直接返回已有的shmid; //已有此key的shm但size不满足要求,同样失败返回-1.
废话不多说, 赶紧上代码,首先是server端,开辟共享内存shm并写入内容进去:
#include <stdio.h> //#include <unistd.h> #include <sys/types.h> #include <sys/ipc.h> #include <sys/shm.h> #define SHM_PATH "/var/run/pnkey" #define SHM_SIZE 128 int main(){ key_t key = ftok(SHM_PATH, 0x6666); //file to key,传入的文件SHM_PATH必须存在(权限不要求),否则失败返回-1 if(key<0){ printf("shm key return -1. Please contact the device vendor."); } // //强制创建1块新的共享内存shm,并设置访问权限位. // int shmid = shmget(key, SHM_SIZE, IPC_CREAT|IPC_EXCL|0666); // if(shmid <0 ){ // printf("Failed to get/create share memory with key= 0x%8x.\n", (int)key ); // //先尝试获取已有的shm // shmid = shmget(key, 0, 0); // if(shmid <0 ){ // printf("Failed to retrive share momory with key= 0x%4x.\n", (int)key); // return -1; // } // //查看获取的shm的size // struct shmid_ds * buf; // int rst = shmctl(shmid, IPC_STAT, buf); // if(buf->shm_segsz != SHM_SIZE){ // printf("The retrived SHM has different size.\n"); // return -1; // } // } //获取此key已有的共享内存shm,未找到时创建新的.[可替代上面的手动检索!] int shmid = shmget(key, SHM_SIZE, IPC_CREAT); //attach到进程空间 char * addr = shmat(shmid, NULL , 0); if(addr <= 0 ){ printf("failed to attach share memory.\n"); return -1; } //使用shm,写入 sprintf(addr, "%s", "共享内存,您好~\n"); return 0; }
接着是client端的,查找出已有的共享内存shm,并从中读取
#include <stdio.h> #include <string.h> //#include <unistd.h> #include <sys/types.h> #include <sys/ipc.h> #include <sys/shm.h> #define SHM_PATH "/var/run/pnkey" #define SHM_SIZE 128 int main(){ key_t key = ftok(SHM_PATH, 0x6666); if(key<0){ printf("shm key return -1. Please contact the device vendor."); } char buf[128]; //int shmid = shmget(key, SHM_SIZE, IPC_CREAT); int shmid = shmget(key, SHM_SIZE, 0); if(shmid <0){ printf("Failed to retrive share memory.\n"); return -1; } char * addr = shmat(shmid, NULL, SHM_RDONLY); //只读挂载 if(addr<=0){ printf("Failed to map share memory.\n"); return -1; } //使用shm,打印字符串. strcpy(buf, addr); printf("%s", buf); printf("%s", addr); //可以直接打印,不必strcpy; 但得考虑同步问题,防止读写并发冲突。 return 0; }