目录
一、相关函数
- 头文件
#include <sys/ipc.h>
#include <sys/shm.h>
1.1、shmget :创建共享内存
int shmget(key_t key, size_t size, int shmflg);
- key:创建共享内存的关键字
IPC_PRIVATE:创建新的共享内存
或者由 ftok 函数产生
或者自定义一个key- size:设定共享内存的大小
- shmflg:共享内存的访问权限
0 访问已存在的IPC
IPC_CREAT | 0644:不存在则创建新的IPC
IPC_EXCL和IPC_CREAT一起用 判断IPC是否存在
- 返回值
>0 共享内存ID ,类似文件描述符
-1 出错
1.2、shmat:映射共享内存
void *shmat(int shmid, const void *shmaddr, int shmflg);
- shmid:共享内存的id号
- shmaddr:指定共享内存在当前进程中的地址,通常为NULL
- shmflg:共享内存的使用权限
SHM_RDONLY:以只读的方式使用此内存段
其他:以读写的方式
- 返回值
>0 共享内存的首地址
-1 失败
1.3、 shmdt:解除映射
int shmdt(const void *shmaddr);
- addr:调用shmat时返回的共享内存首地址
- 返回值
0 成功
-1 失败
1.4、shmctl:对共享内存的一些操作
int shmctl(int shmid, int cmd, struct shmid_ds *buf);
- shmid:共享内存的id号
- cmd:对共享内存的操作
IPC_RMID :删除共享内存段
IPC_STAT:获取shmid_ds结构,并将其放在由buf指向的结构中
IPC_SET:按buf指向结构中的值设定此段相关结构中的一些内容
SHM_LOCK:将共享内存锁定在内存中
SHM_UNLOCK:解锁- buf :设置共享内存时需要的数据或接收共享内存属性的内存地址
删除共享内存时可以为NULL
二、简单应用
- 共享内存不依赖与进程而存在(只要不主动删除,进程退出了,共享内存还在)
- 键key可以自己指定(>0),也可以通过ftok生成
- 可以通过键或shmid再次访问共享内存
- 键>0 和 shmid 都是全局唯一的
- 键为IPC_PRIVATE 时 = 0,不能通过此键访问共享内存,只会创建
- 对于不同的进程
同一个key,shmget()返回的id一样
同一个shmid,shmat()返回的地址一样 - 可以同时读写共享内存
2.1、 不关联文件:读/写
#include <stdio.h>
#include <stdlib.h>
#include <sys/shm.h>
#define KEY 10//只要不和已有的一样,可任意设置
int main() {
int id;
char *buf;
//创建共享内存 大小为1024
id = shmget(KEY,1024,IPC_CREAT | 0644);
if(id == -1){
perror("shmget");
exit(1);
}
printf("id = %d\n", id);
//映射共享内存
buf = (char *) shmat(id,NULL,0);
printf("buf : %p\n",buf);
//写程序
for(int i = 0;i<10;i++){
buf[i] = (char)('a'+i);
}
printf("write : %s\n",buf);
//读程序
//printf("read : %s\n",buf);
shmdt(buf);//取消映射
//shmctl(id,IPC_RMID,NULL);//删除共享内存
return 0;
}
- 使用ipcs命令查看共享内存
$ ipcs
key = 0x0000000a 换算成十进制就是 10
shmid =10 是按最小可用来分配的
- 加 IPC_EXCL再执行write / 删除 IPC_EXCL再执行write
- ipc对象只能由一方创建
2.2、 关联文件:读/写
#include <stdio.h>
#include <stdlib.h>
#include <sys/shm.h>
#include <unistd.h>
#define PATH "./shm" //设置共享内存要关联的文件
#define Proj_Id 16 //只要不和已有的一样,可任意设置
typedef struct {
char msg[10];
int num;
}Data;
int main() {
int key,shm_id,size;
Data *buf;
/*将关联文件转化为key */
key = ftok(PATH,Proj_Id);
if(key == -1){
perror("ftok");
exit(1);
}
//也可以不关联文件,自己设置key的值
// key = 16; //只要不和已有的一样,可任意指定
printf("key = %d\n",key);
/*创建共享内存 大小为size */
size = sizeof(Data)*10;
printf("size = %d\n",size);
shm_id = shmget(key, size,IPC_CREAT | 0644);
if(shm_id == -1){
perror("shmget");
exit(1);
}
printf("shm_id = %d\n", shm_id);
/*映射共享内存 */
buf = (Data *) shmat(shm_id,NULL,0);
printf("buf : %p\n",buf);
printf("开始写入:\n");
for(int i = 0;i<10;i++){
//注释下面两行即可变成读程序
(buf+i)->msg[0] = (char)('a'+i);
(buf+i)->num = i+1;
printf("num = %d, msg = %s \n",(buf+i)->num, (buf+i)->msg);
sleep(1);
}
printf("写入结束:\n");
shmdt(buf);
return 0;
}