ILD

System V shared memory 学习
作者:Yuan Jianpeng 邮箱:yuanjp89@163.com
发布时间:2022-6-29 站点:Inside Linux Development

shared memory有两一种,一种是更老的但是兼容性更好的 System V shared memory。一种是POSIX shared memory。

man shm_overview 可以查看POSIX shared memory的介绍。


接口


       #include <sys/ipc.h>

       #include <sys/shm.h>


        key_t ftok(const char *pathname, int proj_id);

        int shmget(key_t key, size_t size, int shmflg);

        int shmctl(int shmid, int cmd, struct shmid_ds *buf);

        void *shmat(int shmid, const void *shmaddr, int shmflg);

        int shmdt(const void *shmaddr);


key

system v 的ipc,使用key来标识一个ipc。key相同,那创建或者获取的就是同一个ipc。


为了得到一个key。提供了ftok()接口,传入一个文件路径和project id返回一个key。当文件和project id相同时,返回的key就相同。

project id使用低8位,同时手册说如果project id为0,那行为是未定义的,但是测试是可以为0的。


    Today,  proj_id  is  an int, but still only 8 bits are used.  

    Typical usage has an ASCII character proj_id, that is why the behavior is said to be undefined when proj_id is zero.


测试key的结果:


key = ftok("test.c", 0);

key = ftok("test.c", 1);


sizeof(key)等于4,说明key是一个32位整数。

上述2行代码,得到的key分别为:0x2c498 和 0x102c498。test.c的inode为0x40c498。device为:Device: 802h/2050d,即0x802。


所以可以推断key的构造方法:

高8位:project id的低8位。

接下来8位:device的低8位。

低16位:inode的低16位。


shmget

创建一个新的share memory,或者获得一个新的share memory。返回 the  identifier of the System V shared memory segment。

注意这个id不是文件描述符,不能也不需要使用close关闭。

当使用shmctl删除一个share memory,且所有的使用者都shmdt后,这个share memory就被内核释放了。不需要像fd一样close。


第一个参数key,通常使用ftok获得,当然你也可以有自己的策略,只要保证key唯一即可。


第二个参数size,是要创建的shared memory segment的大小,如果不创建,这个参数不被使用,可以传入0。

大小向上对齐到PAGE_SIZE。(rounded up to a multiple of PAGE_SIZE)。


第三个参数shmflg:

IPC_CREAT 创建新的segment。

IPC_EXCL 和IPC_CREAT配合使用,如果segment已经存在,那么返回失败。


shmflg的低9位用来指定权限和linux系统的文件权限一样。所以创建的时候,一定要指定权限,否则shmat会提示没有权限:

IPC_CREAT|IPC_EXCL|0644


shmat

将share memory绑定到一个地址,这样就可以通过这个地址读写共享内存了。

attaches the System V shared memory segment identified by shmid to the address space of the calling process。


第一个参数是shmid,使用shmget获得。


第二个参数shmaddr,是地址,指示如何分配地址。

如果为NULL,则系统选择一个未使用的,对齐到page的地址。


第三个参数是 shmflg,可以为 SHM_RND等。


shmdt

shmat的反向操作,传入shmat的返回值。解绑share memory


detaches  the shared memory segment located at the address specified by shmaddr from the address space of the calling process.


shmctl

控制一个shared memory。可以获得信息、删除shared memory。这里主要用的是删除shared memory。


shmctl(shmfd, IPC_RMID, NULL)


删除可以在shmdt之前,如果删除的时候,还有用户attach了,那么系统不会删除,等最后一个用户shmdt的时候,才会删除。



参考:

https://stackoverflow.com/questions/26120212/implementing-shared-memory-without-root-privilege





Copyright © linuxdev.cc 2017-2024. Some Rights Reserved.