key_t ftok(const char *pathname, int proj_id);
- fname就时你指定的文件名(该文件必须是存在并且能够访问的),
- id是子序号,虽然为int,可是只有8个比特被使用(0-255),默认写1。
- 当成功执行的时候,一个key_t值将会被返回,不然 -1 被返回。
shmget(100,4096,shmflg);
- shmflg: 创建共享内存的时候使用,类似于open函数是否存在
- IPC_CREAT: 创建共享内存
- IPC_CREAT | IPC_EXCL: 检测共享内存是否存在
- 返回值:
shmat(shmid,void* shmaddr,int shmflg);
- shmaddr: 写NULL->委托内核区指定
- shmflg: 操作权限
- 返回值
- 成功: 共享内存的起始地址
- 失败: (void*) -1
shmctl(shmid,int cmd,struct shmid_ds *buf);
- cmd: 对共享内存的操作
- IPC_STAT: 获取共享内存的状态
- IPC_SET: 设置共享内存状态
- IPC_RMID: 标记共享内存要被销毁
- buf: 为第二个参数服务的
- cmd == IPC_STAT: 获取共享内存的具体状态信息
- cmd == IPC_SET: 自定义共享内存的状态,设置到共享内存中去
- cmd == IPC_RMID: 直接指定为NULL
- 返回值
写入共享内存
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <string.h>
#include <sys/ipc.h>
#include <sys/shm.h>
int main(int argc, char *argv[])
{
// 创建共享内存
int shmid = shmget(100,4096,IPC_CREAT|0664);
// 和当前进程关联
void* ptr = shmat(shmid,NULL,0);
// 写共享内存
char *pt = "这是一个块共享内存";
memcpy(ptr,pt,strlen(pt)+1);
printf("按任意键继续\n");
getchar();
// 解除关联
shmdt(ptr);
// 删除共享内存
shmctl(shmid,IPC_RMID,NULL);
return 0;
}
读取共享内存
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <string.h>
#include <sys/ipc.h>
#include <sys/shm.h>
int main(int argc, char *argv[])
{
// 打开共享内存
int shmid = shmget(100,0,0);
// 和当前进程关联
void* ptr = shmat(shmid,NULL,0);
// read共享内存
printf("%s\n",(char*)ptr);
printf("按任意键继续\n");
getchar();
// 解除关联
shmdt(ptr);
// 删除共享内存
shmctl(shmid,IPC_RMID,NULL);
return 0;
}
思考问题
- 问题1: 操作系统如何知道一块共享内存被多少进程关联
- 共享内存维护了一个结构体struct shmid_ds这个结构体中有要给成员shm_nattch
- shm_nattch中记录了关联的进程的个数
- 问题2: 是不是可以对共享内存进行多次删除->多次调用shmctl
- 可以多次操作
- 因为shmctl函数是标记删除共享内存,不是直接删除
- 什么时候被真正删除了?
- 当关联这块共享内存进程个数 == 0的时候,真正被删除了
ipcs -m 查看共享内存
