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);
}