共享内存是实现进程间通信的又一个策略。
与管道在逻辑上相似,用户可以向OS申请,在物理内存中开辟一块空间,OS开辟并向上层返回这块空间的起始地址。需要通信的双方将这块空间通过页表映射,各自的挂载到自己进程地址空间的共享区。通信双方通过访问这一共同的资源进而实现通信。
接口:
size_t size:要申请的内存大小,单位是字节
int shmflg:IPC_CREAT,内存不存在就创建,存在就直接获取并返回。
IPC_CREAT| IPC_EXCL,内存不存在就创建,存在就出错返回。这确保申请的共享内存是重新申请的。IPC_EXCL选项不单独使用。
key_t key: 用于标识共享内存唯一性的值。
返回值:申请成功返回共享内存标识符,失败返回-1;
OS系统中存在着多个由不同的需要通信的进程创建的共享内存,OS通过结构体将这些共享内存描述并组织起来。key值是共享内存结构体中的一个成员变量,是一个唯一性标识。
两个无关联的进程通过相同的key值各自向OS申请内存。进程通过ftok(const char *pathname, int proj_id)接口生成一个唯一性标识,ftok()内部封装一套算法,通过用户传入的路径和任务id,生成唯一性的标识。当两个进程向ftok()传入的路径和任务id相同时,生成的key页相同。进程再拿着这个key向OS申请共享内存。
OS先在自己组织的共享内存中通过key判断要申请的空间是否已经存在。如空间已经存在或者不存在,根据shmflg标志来选择相应的策略---不存在就创建/已存在返回错误,申请失败/已存在,挂载到自己的进程地址空间。
该key值如果是由OS自动生成,那么如何将该唯一性的key值传递给需要通信的另一方?所以如果让OS自动生成,就变成了现有鸡还是先有蛋的问题。
通过相同的pathname 和pro_id 可以生成相同的key是用户的约定,并下达给操作系统。
#include<iostream>
#include <sys/types.h>
#include <sys/ipc.h>
#include <errno.h>
#include <unistd.h>#include <sys/shm.h>#define MAX_BUF 1024
using namespace std;int getkey(size_t pro_id)
{char pathname[MAX_BUF];getcwd(pathname,sizeof(pathname));cout<<"pathname:: "<<pathname<<endl;key_t key =ftok(pathname,pro_id);if(key==-1){cout<<"getkey is error\n"<<endl;return -2;}return key;}int Getshm(int size)
{key_t key =getkey(0x8);cout<<"key:: "<<key<<endl;int shm_fd=shmget(key,size,IPC_CREAT | IPC_EXCL);if(shm_fd==-1){perror("shmget error : ");return -3;}cout<<"shm_fd::" <<shm_fd<<endl;} int main()
{Getshm(10);return 0;
}