相关数据结构
struct ipc_namespace
新建IPC对象:shmget()
1.如果找不到相同键值对应的IPC资源,并且要求新建IPC对象
2.Shmget()中第一个参数,键值key == IPC_PRIVATE都会新建一个IPC对象
新建IPC对象的过程:
系统调用sys_shmget()调用ipcget()完成通过键值查找或者新建IPC资源标识符的工作。
ipcget(ns, &shm_ids(ns), &shm_ops, &shm_params)
其中:
(1)ns来自ns = current->nsproxy->ipc_ns;
(2)&shm_ids(ns)对应一个宏,指向ipc_ids对象(这里就是共享内存)的指针
(3)shm_ops,操作函数
(4)Shm_params来自用户传来的信息。
在ipcget()中调用ipcget_new或者ipcget_public函数
(1)预分配,查看存储空间是否足够(避免做了一系列处理后,由于资源不足而失败。)
先通过err = idr_pre_get(&ids->ipcs_idr, GFP_KERNEL);来预分配IPC对象,如果还有足够的存储资源供IPC资源使用,就返回1(之后就来真正的新建IPC资源),如果资源不足,就返回0(此时函数shmget()结束,返回错误码:ENOMEN,没有足够的存储资源)
(2)调用newseg()函数来新建IPC资源。这个函数的返回值就是IPC资源标识符
第一步.首先新建相关资源,特殊文件等等。即shmid_kernel的一个实体。这个实体中有第一个成员就是kern_ipc_perm成员,它主要是装载着键值和进程的一些信息及权限等内容 。
struct kern_ipc_perm
{
spinlock_t lock;
int deleted;
intid; //IPC资源标识符
key_tkey; //魔数,
uid_t uid;
gid_t gid;
uid_t cuid;
gid_t cgid;
umode_t mode;
unsigned longseq;// 序数
void *security;
};
第二步,通过IDR机制,把这个kern_ipc_perm实例的指针关联到一个整数上去。这个整数就是内核内部ID。每个内核内部ID都会关联到相应的kern_ipc_perm实例上。
在newseg()函数中调用id = ipc_addid(&shm_ids(ns), &shp->shm_perm, ns->shm_ctlmni);
Ipc_addid()完成的工作是通过IDR机制把新建的kern_ipc_perm和一个内核ID做关联,然后用过 ipc_buildid(id, new->seq)函数来把生成一个唯一的IPC资源标志符,把这个标识符放到&shp->shm_perm中的id成员里去。
在newseg()中
struct shmid_kernel *shp;
//shmid_kernel结构的第一个成员shm_perm就是kern_ipc_perm
shp->shm_perm.key = key;
id = ipc_addid(&shm_ids(ns), &shp->shm_perm, ns->shm_ctlmni);
//在这个函数中,会把IPC资源标识符填到shp->shm_perm->id中去。
第三步 对于共享内存,还要file->f_dentry->d_inode->i_ino = shp->shm_perm.id;
查找key对应的IPC资源标志符:
因为Shmget()中第一个参数,键值key != IPC_PRIVATE。所以我们要先来查找是不是有这个key值对应的IPC资源。
在ipcget()中ipcget_public()中调用
struct kern_ipc_perm *ipcp;
ipcp = ipc_findkey(ids, params->key);
在ipc_findkey中调用idr_find(&ids->ipcs_idr, next_id);
//使用IDR机制,返回一个kern_ipc_perm的对象。这个对象包含有IPC资源标志符。
shmget的过程图:
关于新建IPC资源对象中
(1)shmid_kernel中除了kern_ipc_perm外,还有一个重要的成员struct *file shm_file。这个数据结构是内核用来描述共享内存专用的。这个指针是为了把共享内存以文件映射的方式与进程关联的。
它存放文件对象的地址。每个IPC共享内存区与属于shm的特殊文件系统的一个普通文件相关联。
因为shm文件系统在系统目录树中没有安装点,因此,用户不能通过普通的VFS系统调用打开并访问它的文件。但是,只要进程“附加”(shmat())一个内存段,内核就调用do_nmap(),并在进程的地址空间中创建文件的一个新的共享内存映射。
与IPC共享内存对应的内存区是用vm_area_struct对象描述的。它的vm_file字段指回特殊文件的文件对象,而特殊文件又依次引用目录项对象(struct dentry)和索引节点对象(struct inode)。存放在索引节点的i_ino字段的索引节点号实际上是IPC共享内存区的内核内部ID,因此,索引节点对象间接引用shmid_kernel描述符。
对于任何共享内存映射,通过address_space对象把页框包含在页高速缓存中,而address_space对象包含在索引节点中,而且被索引节点的i_mapping字段引用。