共享内存使用方法

来源:互联网 发布:儿童听故事软件 编辑:程序博客网 时间:2024/06/08 06:03
可以通过命令
ipcs -a查看所有的IPC对象使用情况
ipcs -m 查看共享内存
ipcs -q 查看消息队列
ipcs -s 查看信号灯集
ipcrm -m shmid 删除shmid的共享内存
ipcrm -q msgid 删除消息队列
ipcrm -s semid 删除信号灯集
共享内存是一种最为高效的进程间通信方式,进程可以直接读写内存,而不需要任何数据的拷贝
为了在多个进程间交换信息,内核专门留出了一块内存区,可以由需要访问的进程将其映射到自己的私有地址空间
进程就可以直接读写这一内存区而不需要进行数据的拷贝,从而大大提高效率
由于多个进程共享一段内存,因此也需要依靠某种同步机制,如互斥锁和信号量等。
int shmget(key_t key, size_t size, int shmflg);
功能:创建或打开一段共享内存
参数:
key:IPC_PRIVATE代表创建私有共享内存(创建出来的共享内存的key值为0),每次创建都会创建新的共享内存。传入其他key值,可以使其他进程通过key值来得到同一个共享内存。
size:申请共享内存的大小
shmflg:PIC_CREAT创建共享内存|0666、PIC_EXCL如果存在报错
返回值:成功返回创建的共享内存的shmid,失败返回-1并且设置errno。
如:shm_id=shmget(ftok("/",'a'),128,PIC_CREAT|PIC_EXCL|0666);
创建过之后在打开就可以shm_id=shmget(ftok("/",'a'),0,0);因为之前已经创建好了,所以写0就可以了。当然这样也不会错shm_id=shmget(ftok("/",'a'),128,0666);
key_t ftok(const char *pathname, int proj_id);
功能:获取键值
参数:
pathname:路径
proj_id:尽量填写一个字符(0-255)
返回值:成功返回key值,失败返回:-1
ftok()函数会获取第一个参数(文件或目录)的属性信息,并把ftok()的第二个参数的后8位,st_dev的后两位,st_ino的后四位,构成了一个键值。
这个函数在信号灯集里面提及过了,这里就不详细说明了。
void *shmat(int shmid, const void *shmaddr, int shmflg);
功能:映射共享内存
参数:shmid:共享内存ID
shmaddr:一般设为NULL,操作系统帮我们选择,否则需要自定义映射地址
shmflg:SHM_RDONLY为只读,0表示可读可写
返回值:成功返回映射后的地址,失败返回-1
char *p=shmat(shm_id,NULL,0);
int shmdt(const void *shmaddr);
功能:取消映射共享内存
参数:取消映射的地址
返回值:成功返回0,失败返回-1;
shmdt(p);
int shmctl(int shmid, int cmd, struct shmid_ds *buf);
功能:对共享内存进行操作
参数:shmid:共享内存的ID
cmd:IPC_STAT表示获取共享内存的信息
IPC_SET表示设置共享内存的信息
IPC_RMID表示删除共享内存
返回值:成功返回0,失败返回-1
struct shmid_ds {
struct ipc_perm shm_perm; /* Ownership and permissions */
size_t shm_segsz; /* Size of segment (bytes) */
time_t shm_atime; /* Last attach time */
time_t shm_dtime; /* Last detach time */
time_t shm_ctime; /* Last change time */
pid_t shm_cpid; /* PID of creator */
pid_t shm_lpid; /* PID of last shmat(2)/shmdt(2) */
shmatt_t shm_nattch; /* No. of current attaches */
...
};
例如:shmctl(shm_id,IPC_RMID,NULL);

在还有进程映射共享内存的情况下,对共享内存进行IPC_RMID操作会使这段共享内存变为dest状态,key值变为0,当nattch映射数为0的时候自动被删除。
共享内存结合信号的代码如下: