目录
1.特点
(1)共享内存是一种最为高效的进程间通信方式,进程可以直接读写内存,而不需要任何数据的拷贝。
(2)为了在多个进程间交换信息,内核专门留出了一块内存区,可以由需要访问的进程将其映射到自己的私有地址空间。进程就可以直接读写这一内存区而不需要进行数据的拷贝,从而大大提高的效率。
(3) 由于多个进程共享一段内存,因此也需要依靠某种同步机制,如互斥锁和信号量等
2.使用步骤
(1) 创建 key值
(2) 创建或打开共享内存
(3) 映射共享内存到用户空间
(4) 撤销映射
(5) 删除共享内存
3.函数接口
3.1创建key值
key_t ftok( constchar *pathname, int proj_id);
功能:创建出来的具有唯一映射关系的一个key值,帮助操作系统用来标识一块共享内存
参数:Pathname:已经存在的可访问文件的名字
Proj_id:一个字符(因为只用低8位)
返回值:成功:key值
失败:-1
// 将文件的索引节点号取出ls -i,前面加上proj_id得到key_t的返回值。如指定文件的索引节点号为65538,换算成16进制为 0x010002取后4位,而你指定的ID值为38,换算成16进制为0x26,则最后的key_t返回值为0x26010002。中间的01是系统编号。
3.2创建或打开共享内存
int shmget( key_t key, size_t size, int shmflg);
功能:创建或打开共享内存
参数:
key 键值
size 共享内存的大小
shmflg IPC_CREAT | IPC_EXCL | 0777
返回值:成功 shmid
出错 -1
//当IPC_CREAT | IPC_EXCL时, 如果没有该块共享内存,则创建,并返回共享内存ID。若已有该块共享内存,则返回-1。
3.3映射共享内存
void *shmat( int shmid, constvoid *shmaddr, int shmflg); //attaches
功能:映射共享内存,即把指定的共享内存映射到进程的地址空间用于访问
参数:
shmid 共享内存的id号
shmaddr 一般为NULL,表示由系统自动完成映射
如果不为NULL,那么有用户指定
shmflg:SHM_RDONLY就是对该共享内存只进行读操作
0 可读可写
返回值:成功:完成映射后的地址,
出错:-1(地址)
用返回值判断用法:if((p =(char*)shmat(shmid,NULL,0))==(char*)-1)
3.4取消映射
int shmdt( constvoid *shmaddr); //detaches
功能:取消映射
参数:要取消的地址
返回值:成功 0
失败的 -1
3.5删除共享内存
int shmctl( int shmid, int cmd, struct shmid_ds *buf); //control
功能:(删除共享内存),对共享内存进行各种操作
参数:
shmid 共享内存的id号
cmd IPC_STAT 获得shmid属性信息,存放在第三参数
IPC_SET 设置shmid属性信息,要设置的属性放在第三参数
IPC_RMID 删除共享内存,此时第三个参数为NULL即可
buf shmid 所指向的共享内存的地址,空间被释放以后地址就赋值为null
返回:成功0
失败-1
用法: shmctl( shmid, IPC_RMID, NULL);
4.命令
ipcs -m: 查看系统中的共享内存
ipcrm -m shmid:删除共享内存
ps: 可能不能直接删除掉还存在进程使用的共享内存。
这时候可以用 ps -ef对进程进行查看,kill 掉多余的进程后,再使用 ipcs查看。
5.基本操作
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/shm.h>
#include <stdio.h>
#include <errno.h>
int main(int argc, char const *argv[])
{
// 创建key值
key_t key;
key = ftok("shm.c", 'd');
if (key < 0)
{
perror("key error");
return -1;
}
printf("key:%#x\n", key);
// 创建或打开共享内存
// 不存在创建,存在返回-1
int shmid;
shmid = shmget(key, 128, IPC_CREAT | IPC_EXCL | 0777);
if (shmid <= 0)
{
if (errno == EEXIST) // 如果存在,直接打开,返回id
{
shmid = shmget(key, 128, 0777);
}
else
{
perror("shmid error");
return -1;
}
}
printf("shmid:%d\n", shmid);
// 映射共享内存
char *p;
p = (char *)shmat(shmid, NULL, 0);
if (p == (char *)-1)
{
perror("shmat err");
return -1;
}
// 操作共享内存
scanf("%s", p);
// printf("%s \n", p);
// 取消映射
shmdt(p);
// 删除共享内存
shmctl(shmid, IPC_RMID, NULL);
return 0;
}
标签:IPC,映射,int,间通信,shmid,key,进程,共享内存
From: https://blog.csdn.net/weixin_67273669/article/details/140225842