https://linux.die.net/man/2/shmat
shmat, shmdt 共享内存的操作
概要
#include <sys/types.h>#include <sys/shm.h>
void *shmat(int shmid, const void *shmaddr, int shmflg);
int shmdt(const void *shmaddr);
描述
shmat()把由shmid标识的共享内存关联到调用进程的地址空间。关联地址由 shmaddr指定,遵循如下规则的其中之一。
- 如果 shmaddr 不是 NULL, 并且shmflg指定了SHM_RND, 关联的地址与shmaddr 向下舍入到最近的SHMLBA的倍数。否则, shmaddr必须是 page-aligned 地址。
- 如果shmflg中设置了SHM_RDONLY,则该共享地址段是只读的,当前调用进程必须只设置读权限。如果shmflg中没有设置SHM_RDONLY,则该共享地址段是可读写的, 该进程必须设置读写权限。对于只写共享内存段没有指定和说明。
- shmflg中可能会设置SHM_REMAP (只有linux版本支持), 来标识共享内存段的映射可以替换替换已经存在的映射,起始地址是shmaddr, 连续共享内存段大小的内存。通常情况下,如果该地址范围已经存在一个映射,会返回EINVAL 错误。这种情况下,shmaddr不能是NULL。
- 调用进行的brk(2) 值不能被attach操作改变。当进程退出时,共享内存段会自动的detach。相同的共享内存段可能被attach成只读或读写的,或多个,在进程的地址空间内。
成功的shmat()调用会更新共享内存段所关联的shmid_ds 结构体的成员,如下所示:
- shm_atime,设置成当前时间
- shm_lpid,设置成当前调用进程的process-ID。
- shm_nattch, 加1.
shmdt() 是从调用进程的地址空间中detach shmaddr指定的共享内存段所在的地址。shmat的逆操作。to-be-detached 的共享内存段必须是由shmat()调用返回的shmaddr。
一个成功的shmdt()调用会更新共享内存段所关联的shmid_ds 结构体的成员,如下所示:
- shm_atime,设置成当前时间
- shm_lpid,设置成当前调用进程的process-ID。
- shm_nattch, 减1.如果变成了0, 共享内存段被标识要进行deletion,该共享内存段会被删除。fork(2)的子进程会继承关联的共享内存段。
- 在 execve(2)调用之后,所有关联的共享内存段会从该进程中detach。
- _exit(2)调用后,该进程关联的所有共享内存段都会被detach。
返回值
如果shmat()成功,返回共享内存段在该进程中关联地址;如果出错,返回(void *) -1, errno 来标识出错的原因。
如果shmdt()成功,则返回0;否则,返回(void *) -1, errno 来标识出错的原因。
shmat()的出错码
- EACCES, the calling process does not have the required permissions for the requested attach type, and does not have the CAP_IPC_OWNER capability.
- EIDRM, shmid points to a removed identifier.
- EINVAL, Invalid shmid value, unaligned (i.e., not page-aligned and SHM_RND was not specified) or invalid shmaddr value, or can't attach segment at shmaddr, or SHM_REMAP was specified and shmaddr was NULL.
- ENOMEM, Could not allocate memory for the descriptor or for the page tables.
shmdt() 的出错码
- EINVAL, There is no shared memory segment attached at shmaddr; or, shmaddr is not aligned on a page boundary.
说明:
调用shmat()时,最好设置shmaddr为NULL,这样共享内存段的关联会具有可移植性。值得注意的是,这种方式进行的共享内存段的关联,不同的进程会关联到不同的地址。因此,任何一个保持共享内存的指针必须是相对地址(典型的是,从共享内存段的起始地址开始)而不是绝对地址。
下面的系统参数会影响到shmat()操作:
- SHMLBA:Segment low boundary address multiple. Must be page aligned. For the current implementation the SHMLBA value is PAGE_SIZE.
- The implementation places no intrinsic limit on the per-process maximum number of shared memory segments (SHMSEG).