shmop() - Unix,Linux系统调用
广告
名称shmop - 共享内存操作概要
#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,系统将选择合适的(未使用的)地址来附加段。 如果shmaddr不为NULL并且在shmflg中指定了SHM_RND,则附加发生在等于shmaddr向下舍入到SHMLBA的最近倍数的地址。否则,shmaddr必须是页面对齐的地址,附加在此地址处发生。 如果在shmflg中指定了SHM_RDONLY,则附加段用于读取,并且进程必须对该段具有读取权限。否则,该段用于读写,并且进程必须对该段具有读写权限。没有写入共享内存段的概念。 可以在shmflg中指定(Linux专用)SHM_REMAP标志,以指示段的映射应替换从shmaddr开始并持续段大小的范围内任何现有映射。(通常,如果此地址范围内已存在映射,则会产生EINVAL错误。)在这种情况下,shmaddr不能为NULL。 调用进程的brk(2)值不会因附加而改变。段将在进程退出时自动分离。同一段可以作为读段和读写段附加,并且在进程的地址空间中可以附加多次。 成功的shmat()调用会更新与共享内存段关联的shmid_ds结构(参见shmctl(2))的成员,如下所示:
标签 | 描述 |
|
shm_atime设置为当前时间。 |
|
shm_lpid设置为调用进程的进程ID。 |
|
shm_nattch递增1。 |
shmdt() 将位于由shmaddr指定的地址的共享内存段从调用进程的地址空间分离。要分离的段必须当前附加,并且shmaddr等于附加shmat()调用返回的值。 |
在成功的shmdt()调用中,系统会更新与共享内存段关联的shmid_ds结构的成员,如下所示: |
|
shm_dtime设置为当前时间。 |
|
shm_lpid设置为调用进程的进程ID。 |
|
shm_nattch递减1。如果它变为0并且该段被标记为要删除,则该段将被删除。 |
系统调用
标签 | 描述 |
fork() | 在fork()之后,子进程继承附加的共享内存段。 |
exec() | 在exec()之后,所有附加的共享内存段都将从进程中分离。 |
exit() | 在exit()时,所有附加的共享内存段都将从进程中分离。 |
返回值成功时,shmat()返回附加共享内存段的地址;出错时,返回(void *) -1,并设置errno以指示错误的原因。成功时,shmdt()返回0;出错时,返回-1,并设置errno以指示错误的原因。 错误当shmat()失败时,errno设置为以下之一:
标签 | 描述 |
EACCES | 调用进程不具有请求的附加类型的所需权限,并且不具有CAP_IPC_OWNER能力。 |
EINVAL | 无效的shmid值,未对齐(即,未页面对齐且未指定SHM_RND)或无效的shmaddr值,或在brk()处附加失败,或指定了SHM_REMAP且shmaddr为NULL。 |
ENOMEM | 无法为描述符或页表分配内存。 |
当shmdt()失败时,errno设置如下:
标签 | 描述 |
EINVAL | 在shmaddr处没有附加的共享内存段;或者,shmaddr未对齐到页面边界。 |
备注使用shmaddr等于NULL的shmat()是附加共享内存段的首选可移植方法。请注意,以这种方式附加的共享内存段可能在不同的进程中附加到不同的地址。因此,在共享内存中维护的任何指针必须设置为相对的(通常相对于段的起始地址),而不是绝对的。在Linux上,即使共享内存段已被标记为要删除,也可以附加它。但是,POSIX.1-2001没有指定此行为,许多其他实现也不支持它。 以下系统参数会影响shmat():
标签 | 描述 |
SHMLBA | 段低边界地址倍数。必须页面对齐。对于当前实现,SHMLBA值为PAGE_SIZE。 |
实现对每个进程共享内存段的最大数量(SHMSEG)没有内在限制。符合标准SVr4, POSIX.1-2001。在SVID 3(或可能更早的版本)中,shmaddr参数的类型从char *更改为const void *,shmat()的返回类型从char *更改为void *。(Linux libc4和libc5具有char *原型;glibc2具有void *。) 参见
广告
|