Linux系统中使用IPC共享内存 (POSIX)

3 篇文章 0 订阅

Linux查看或删除系统中的IPC对象

查看消息队列:ipcs -q
查看共享内存:ipcs -m
查看信号量:ipcs -s
查看所有IPC对象:ipcs -a
删除指定的消息队列:ipcs -q MSG_ID 或者 ipcrm -Q msg_key
删除执行的共享内存:ipcs -m SHM_ID 或者 ipcrm -M shm_key
删除指定的信号量:ipcs -s SEM_ID 或者 ipcrm -S sem_key

检查当前 SHMMIN & SHMMAX :
sysctl -a | grep shmm

 
系统函数说明

key_t ftok(const char *pathname,int proj_id)
说明:ftok函数生成key标识符
参数1:自定义的路径名称
参数2:自定义ID
返回值:一个根据两个参数生成的唯一ID,可用于shmget


int shmget(key_t key,size_t size,int shmflg)
说明:创建一个共享内存块,返回这个共享内存块的标识符shmid
参数1:ftok生成的唯一ID
参数2:需要申请的共享内存的大小(按页来提供,所以size为4k的整数倍)
参数3:创建新的共享内存使用IPC_CREAT,IPC_EXCL  已经存在使用IPC_CREAT(对应文件的O_CREAT或O_EXCL)
返回值:成功返回共享内存的标识符;不成功返回-1,errno储存错误原因。
        EINVAL           参数size小于SHMMIN或大于SHMMAX。
        EEXIST           预建立key所致的共享内存,但已经存在。
        EIDRM            参数key所致的共享内存已经删除。
        ENOSPC        超过了系统允许建立的共享内存的最大值(SHMALL )。
        ENOENT        参数key所指的共享内存不存在,参数shmflg也未设IPC_CREAT位。
        EACCES        没有权限。
        ENOMEM       核心内存不足。


void *shmat(int shm_id, const void *shm_addr, int shmflg)
说明:第一次创建完共享内存时,它还不能被任何进程访问,该函数启动对该共享内存的访问,并把共享内存连接到当前进程的地址空间
参数1:shmget返回的指向内存的ID
参数2:指定共享内存连接到当前进程中的地址位置,通常为空,表示让系统来选择共享内存的地址
参数3:shm_flg是一组标志位,通常为0
返回值:调用成功时返回一个指向共享内存第一个字节的指针,如果调用失败返回-1


int shmdt(const void *shmaddr);
说明:用于将共享内存从当前进程中分离(并不是删除它),使该共享内存对当前进程不再可用
参数1:shmat返回的地址指针
返回值:调用成功时返回0,失败时返回-1


int shmctl(int shm_id, int command, struct shmid_ds *buf);
说明:与信号量的semctl函数一样用来控制共享内存
参数1:shmget返回的指向内存的ID
参数2:command是要采用的操作,下面是他的值:
      IPC_STAT:把shmid_ds结构中的数据设置为共享内存的当前关联值,即用共享内存的当前关联值覆盖shmid_ds的值。
      IPC_SET:如果进程有足够的权限,就把共享内存的当前关联值设置为shmid_ds结构中给出的值
      IPC_RMID:删除共享内存段
参数3:buf是一个结构指针,指向共享内存模式和访问权限的结构
      shmid_ds struct:
      struct shmid_ds
      {
          uid_t shm_perm.uid;
          uid_t shm_perm.gid;
          mode_t shm_perm.mode;
      };

 
一个简易的shm通信头文件实现 供参考

#include <stdio.h>
#include <stdlib.h>
#include <stddef.h>
#include <sys/mman.h>
#include <fcntl.h>
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/shm.h>
#include <unistd.h>
#include <pthread.h>
#include <string.h>
#include <shared_mutex>
#include <mutex>
#include <thread>

#define DATA_SIZE 1024*1024*32

struct bitcq_data
{
    int written; // 0:readable ,1:writeable
    u_char data[DATA_SIZE]; // record write/read data
};

class shmobject
{
public:
    shmobject(char *, int, bool);
    ~shmobject();
    void write_memory(void *, size_t);
    void read_memory(void *, size_t);

private:
    void create_shared_memory();

    bool    rw;         // r(reader) -> 1 / w(writer) -> 0 
    key_t   shm_key;    // shm_key
    int     shm_id;     // auto_gen id
    int     shm_flag;   // IPC_CREAT | IPC_EXCL
    size_t  shm_size;   // memory size
    
    bitcq_data         *shm_ptr;
    pthread_rwlock_t     rwlock;
    std::shared_mutex memoryMutex;
};

shmobject::shmobject(char *filepath, int proj_id, bool rw)
{
    printf("current role is %s\n", rw == 0? "writer" : "reader");

    shm_key = ftok(filepath, proj_id);
    
    if(rw == 0)
    {
        shm_size = sizeof(struct bitcq_data);
        shm_flag = IPC_CREAT | IPC_EXCL | 0666; //0666 means full memory read/write access
    }
    else
    {
        shm_size = 0;
        shm_flag = 0;
    }

    if(shm_key == -1)
    {
        fprintf(stderr, "ftok generate shmid failed!\n");
        exit(EXIT_FAILURE);
    }

    create_shared_memory();

    //pthread_rwlock_init(&rwlock, nullptr);
}

shmobject::~shmobject()
{
    if(shmdt(shm_ptr) == -1)
    {
        fprintf(stderr, "shmdt failed\n");
        exit(EXIT_FAILURE);
    }
    printf("shmdt succeed!\n");

    if(rw == 0)
    {
        if(shmctl(shm_id, IPC_RMID, 0) == -1)
        {
            fprintf(stderr, "shmctl(IPC_RMID) failed!\n");
            exit(EXIT_FAILURE);
        }
        printf("shmctl(IPC_RMID) succeed!\n");
    }

    //pthread_rwlock_destroy(&rwlock);

    exit(EXIT_SUCCESS);
}

void shmobject::create_shared_memory()
{
    printf("shm_key:   %x\n", shm_key);
    printf("shm_size:  %zu\n", shm_size);
    printf("shm_flag:  %d\n", shm_flag); 

    shm_id = shmget(shm_key, shm_size, shm_flag);
    printf("shm_id:    %d\n", shm_id);

    shm_ptr = (bitcq_data *)shmat(shm_id, (void *)0, 0);
    printf("shm_ptr:   %p\n", shm_ptr);

    if(shm_id == -1 || shm_ptr == NULL)
    {
        printf("create shared memory failed!\n");
        exit(EXIT_FAILURE);
    }
}

void shmobject::write_memory(void * ptr, size_t w_size)
{
    //pthread_rwlock_wrlock(&rwlock);

    std::unique_lock<std::shared_mutex> lock(memoryMutex);
    shm_ptr->written = 1;
    memcpy(shm_ptr->data, (u_char *)ptr, w_size);
    shm_ptr->written = 0;

    //pthread_rwlock_unlock(&rwlock);
}

void shmobject::read_memory(void * ptr, size_t r_size)
{
    //pthread_rwlock_rdlock(&rwlock);

    while(shm_ptr->written == 1)
    {
        usleep(1000);
    }

    std::shared_lock<std::shared_mutex> lock(memoryMutex);
    memcpy((u_char *)ptr, (u_char *)shm_ptr->data, r_size);
    
    //pthread_rwlock_unlock(&rwlock);
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值