system v : 共享内存 信号量集
IPC对象操作通用框架:
0x ftok
key值 ==> 申请 ==》读写 ==》关闭 ==》卸载
优点:
- 共享内存效率高
- 没有读写阻塞
操作流程:
key ==》申请对象 ==》映射对象==》读写对象==》撤销映射 ==》删除对象
一、key操作
1. ftok()创建临时键值
#include <sys/types.h>
#include <sys/ipc.h>
key_t ftok(const char *pathname, int proj_id);
功能:通过该函数可以将pathname指定的路径用来以proj_id生成唯一的临时键值。
参数:pathname 路径+名称===》任意文件,只要不会被删除重建即可。
proj_id 整形的数字,一般用ASCII码的单字符,表示与参数1的运算。
返回值:成功 返回唯一键值
失败 -1;
2. 申请对象:shmget()
#include <sys/ipc.h>
#include <sys/shm.h>
ps aux|grep a.out
share memory get IPC_CREAT|0666
int shmget(key_t key, size_t size, int shmflg);
功能:使用唯一键值key向内核提出 共享内存 使用申请
参数:key 唯一键值
size 要申请的共享内存大小
shmflg 申请的共享内存访问权限,八进制表示
如果是第一个申请,则用IPC_CREAT
如果要检测是否存在,用IPC_EXCL
返回值:成功 返回共享内存id,一般用shmid表示
失败 -1;
3. 映射对象:shmat()
share memory attach
void *shmat(int shmid, const void *shmaddr, int shmflg);
功能:将指定shmid对应的共享内存映射到本地内存。
参数:shmid 要映射的本地内存
shmaddr 本地可用的地址,如果不确定则用NULL,表示由系统自动分配。
shmflg 0,表示读写
SHM_RDONLY,只读
返回值:成功 返回映射的地址,一般等于shmaddr
失败 (void*)-1
4. 撤销映射:shmdt()
int shmdt(const void *shmaddr);
功能:将本地内存与共享内存断开映射关系。
参数:shmaddr 要断开的映射地址
返回值:成功 0
失败 -1;
5.删除对象:shmctl()
int shmctl(int shmid, int cmd, struct shmid_ds *buf);
功能:修改共享内存属性,也可以删除指定的共享内存对象。
参数:shmid 要删除的共享内存对象
cmd IPC_RMID 删除对象的宏
buff NULL 表示只删除对象
返回值:成功 0
失败 -1
(1)shm_w.c
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/shm.h>
#include <string.h>
int main(int argc, char *argv[])
{
key_t key = ftok("./",'!');
if(-1 == key)
{
perror("ftok");
exit(1);
}
printf("key is 0x%x\n",key);
int shmid = shmget(key,4096,IPC_CREAT|0666);
if(-1 == shmid)
{
perror("shmget");
exit(1);
}
void* p = shmat(shmid,NULL,!SHM_RDONLY);
if((void *) -1 == p )
{
perror("shmat");
exit(1);
}
strcpy((char*)p,"hello,this is shm test");
shmdt(p);
return 0;
}
(2)shm_r
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/shm.h>
#include <string.h>
int main(int argc, char *argv[])
{
key_t key = ftok("./",'!');
if(-1 == key)
{
perror("ftok");
exit(1);
}
printf("key is 0x%x\n",key);
int shmid = shmget(key,4096,IPC_CREAT|0666);
if(-1 == shmid)
{
perror("shmget");
exit(1);
}
void* p = shmat(shmid,NULL,!SHM_RDONLY);
if((void *) -1 == p )
{
perror("shmat");
exit(1);
}
printf("mem is %s\n",(char*)p);
shmdt(p);
//shmctl(shmid,IPC_RMID,NULL);
return 0;
}
两个命令:
- ipcs -a 查询共享内存,信号量集,消息队列
- ipcrm -s 删除信号量集 / -m 删除共享内存