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 *。) 参见
广告
|