共享内存的使用也是IPC的一种方式,这种方式数据拷贝次数较少,效率较高。
其原理也是在内存中开辟一块公共访问的区域,可以让各个进程连接读写。
共享内存的API函数主要有以下四个
int shmget(key_t key, size_t size, int shmflg);创建或加入共享内存
key_t key:16进制 非0数据。 0x1111 ----我理解为是共享内存块的标号,进程通过key值连到同一个共享内存中。 其中0x0000代表私有private,此时不允许其他进程再接入,其他非零正整数则代表共享的,可以允许进程接入
size_t size: 开辟的共享内存的大小,如果接入已存在的共享内存,必须大小一致,否则会报错
int shmflg:需要填写1.状态:读写执行权限 -- 8进制。 0644 。 第一位的0一定不能省略
2.标志位,常用的是IPC_CREAT,创建一块共享内存,如果存在,就加入这块共享内存
IPC_EXCL是和IPC_CREAT一起使用的,当共享内存存在就会报错
返回值:成功 0, 失败-1, 设置errorno
void *shmat(int shmid, const void *shmaddr, int shmflg);//单个进程获得共享内存的地址,并设置读写权限shmid: shmget 返回值
shmaddr: 想要开辟共享内存的地址。默认NULL内核自动分配。shmflg: SHM_RND 读写。
SHM_RDONLY 只读。
返回值:成功 映射内存首地址, 失败(void *)-1, 设置errorno
int shmdt(const void *shmaddr);//单个进程取消共享内存地址关联取消 进程与共享内存的 关联关系。
返回值:成功 0, 失败-1, 设置errorno
int shmctl(int shmid, int cmd, struct shmid_ds *buf);//共享内存地址的控制,主要使用这个函数关闭共享内存shmid: shmget 返回值
cmd: IPC_RMID 删除 共享内存 (使用这个函数时,key值变为0x0000,不允许其他进程接入,但是这块共享内存并没有关闭,只有当引用计数(就是已连接在共享内存的进程数)变为 0时,才真正关闭,)
对应 参数3 传 NULL
返回值:成功 0, 失败-1, 设置errorno
#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
#include <fcntl.h>
#include <sys/stat.h>
#include <sys/mman.h>
#include <errno.h>
#include <string.h>
#include <sys/ipc.h>
#include <sys/shm.h>
int main()
{
int shmid = shmget(0x0021, 512, 0664|IPC_CREAT|IPC_EXCL);//建立共享内存
if (shmid == -1)
{
printf("shmget is error %d\n", shmid);
return 0;
}
printf("shmget is success!\n, shmid = %d", shmid);
char *buf=NULL;
buf = shmat(shmid, NULL, SHM_RND);//获得共享内存的地址
if (buf==(void*)-1)
{
printf("shmat is error %d\n", shmid);
return 0;
}
memcpy(buf, "hello", 5);
printf("buf is %s\n", buf);
getchar();
getchar();
shmdt(buf);//取消和共享内存的联系
getchar();
int ret = shmctl(shmid, IPC_RMID, NULL);//关闭共享内存
if (ret == -1)
{
printf("shmctl is error %d\n", shmid);
return 0;
}
return 0;
}
linux中查看共享内存的指令:ipcs