Linux下IPC之共享内存的使用方法

基本参考 《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.

getshm()函数,常见的调用示例:

点击查看代码
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端示例代码

废话不多说, 赶紧上代码,首先是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端示例代码

接着是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;
}
上一篇:cmd


下一篇:Docker实现进程隔离的方式