SHMCTL - Linux手册页

Linux程序员手册 第2部分
更新日期: 2020-04-11

名称

shmctl-系统V共享内存控制

出版信息

这个页面是Linux手册页项目5.08版的一部分。有关项目的说明、有关报告错误的信息以及此页面的最新版本,请访问https://www.kernel.org/doc/man-pages/

另外参见

mlock(2),setrlimit(2),shmget(2),shmop(2),功能(7),sysvipc(7)

遵循规范

POSIX.1-2001,POSIX.1-2008,SVr4。

备注

在Linux或任何版本的POSIX上,都不需要包含和。但是,一些旧的实现需要包含这些头文件,并且SVID也记录了这些头文件。打算移植到这样的旧系统的应用程序可能需要包括这些头文件。

ipcs(1)程序使用IPC_INFO,SHM_STAT和SHM_INFO操作来提供有关已分配资源的信息。将来,它们可能会修改或移至/ proc文件系统接口。

Linux允许进程附加(shmat(2))已使用shmctl(IPC_RMID)标记为删除的共享内存段。此功能在其他UNIX实现上不可用;可移植的应用程序应避免依赖它。

shmid_ds结构中的各个字段在Linux 2.2下的类型为short,而在Linux 2.4下的类型为long。要利用此优势,在glibc-2.1.91或更高版本下进行重新编译就足够了。 (内核通过cmd中的IPC_64标志区分新旧呼叫。)

返回值

成功的IPC_INFO或SHM_INFO操作将返回内核内部阵列中使用最高的条目的索引,该条目记录有关所有共享内存段的信息。 (此信息可以与重复的SHM_STAT或SHM_STAT_ANY操作一起使用,以获得有关系统上所有共享内存段的信息。)成功的SHM_STAT操作返回其索引在shmid中给出的共享内存段的标识符。其他操作成功返回0。

如果出错,则返回-1,并正确设置errno。

语法

#包括
#包括

int shmctl(int shmid,int cmd,struct shmid_ds * buf);复制代码

错误说明

EACCES
请求了IPC_STAT或SHM_STAT,并且shm_perm.mode不允许对shmid进行读取访问,并且调用过程在控制其IPC名称空间的用户名称空间中不具有CAP_IPC_OWNER功能。
EFAULT
参数cmd的值为IPC_SET或IPC_STAT,但是buf指向的地址不可访问。
EIDRM
shmid指向已删除的标识符。
EINVAL
shmid不是有效的标识符,或者cmd不是有效的命令。或:对于SHM_STAT或SHM_STAT_ANY操作,shmid中指定的索引值引用当前未使用的阵列插槽。
ENOMEM
(在2.6.9版以后的内核中)指定了SHM_LOCK,并且要锁定的段的大小意味着锁定的共享内存段中的总字节数将超过调用进程的实际用户ID的限制。此限制由RLIMIT_MEMLOCK软资源限制定义(请参阅setrlimit(2))。
EOVERFLOW
尝试IPC_STAT,并且GID或UID值太大,无法存储在buf指向的结构中。
EPERM
尝试使用IPC_SET或IPC_RMID,并且调用过程的有效用户ID不是创建者(在shm_perm.cuid中找到)或所有者(在shm_perm.uid中找到)的有效用户ID,并且该过程没有特权(Linux:做到了)不具备CAP_SYS_ADMIN功能)。
或者(在2.6.9之前的内核中)指定了SHM_LOCK或SHM_UNLOCK,但是该进程没有特权(Linux:不具有CAP_IPC_LOCK功能)。 (从Linux 2.6.9开始,如果RLIMIT_MEMLOCK为0并且调用者没有特权,也会发生此错误。)

说明

shmctl()在SystemV共享内存段上执行cmd指定的控制操作,该段的标识符在shmid中给出。

buf参数是shmid_ds结构的指针,其定义如下:

struct shmid_ds {
    struct ipc_perm shm_perm;    /* Ownership and permissions */
    size_t          shm_segsz;   /* Size of segment (bytes) */
    time_t          shm_atime;   /* Last attach time */
    time_t          shm_dtime;   /* Last detach time */
    time_t          shm_ctime;   /* Creation time/time of last
                                    modification via shmctl() */
    pid_t           shm_cpid;    /* PID of creator */
    pid_t           shm_lpid;    /* PID of last shmat(2)/shmdt(2) */
    shmatt_t        shm_nattch;  /* No. of current attaches */
    ...
};

shmid_ds结构的字段如下:

shm_perm
这是一个ipc_perm结构(请参见下文),用于指定对共享内存段的访问权限。
shm_segsz
共享内存段的大小(以字节为单位)。
shm_cpid
创建共享内存段的进程的ID。
shm_lpid
在该段上执行shmat(2)或shmdt(2)系统调用的最后一个进程的ID。
shm_nattch
带有此段的进程数。
shm_atime
附加此段的最后一个shmat(2)系统调用的时间。
shm_dtime
断开tgis段的最后一次shmdt(2)系统调用的时间。
shm_ctime
创建段的时间或最后一个shmctl()IPC_SET操作的时间。

ipc_perm结构定义如下(突出显示的字段可使用IPC_SET设置):

struct ipc_perm {
    key_t          __key;    /* Key supplied to shmget(2) */
    uid_t          uid;      /* Effective UID of owner */
    gid_t          gid;      /* Effective GID of owner */
    uid_t          cuid;     /* Effective UID of creator */
    gid_t          cgid;     /* Effective GID of creator */
    unsigned short mode;     /* Permissions + SHM_DEST and
                                SHM_LOCKED flags */
    unsigned short __seq;    /* Sequence number */
};

ipc_perm结构的mode字段的最低9位定义了共享内存段的访问权限。权限位如下:

0400Read by user
0200Write by user
0040Read by group
0020Write by group
0004Read by others
0002Write by others

系统未使用位0100、0010和0001(执行位)。 (为了执行带有SHM_EXEC标志的shmat(2)调用,不必对段具有执行权限。)

cmd的有效值为:

IPC_STAT
将信息从与shmid相关联的内核数据结构复制到buf指向的shmid_ds结构中。调用方必须对共享内存段具有读取权限。
IPC_SET
将buf指向的shmid_ds结构的某些成员的值写入与此共享内存段关联的内核数据结构,同时还更新其shm_ctime成员。可以更改以下字段:shm_perm.uid,shm_perm.gid和shm_perm.mode(最低9位)。调用过程的有效UID必须与共享内存段的所有者(shm_perm.uid)或创建者(shm_perm.cuid)相匹配,否则调用者必须具有特权。
IPC_RMID
标记要销毁的线段。实际上,只有在最后一个进程将其分离后(即,关联结构shmid_ds的shm_nattch成员为零时),该段才真正被破坏。调用者必须是该细分的所有者或创建者,或者必须具有特权。 buf参数将被忽略。
如果已将某个段标记为要销毁,则将设置IPC_STAT检索的关联数据结构中shm_perm.mode字段的(非标准)SHM_DEST标志。
调用者必须确保片段最终被销毁;否则,其错误页面将保留在内存或交换中。
另请参阅proc(5)中对/ proc / sys / kernel / shm_rmid_forced的描述。
IPC_INFO(Linux-specific)
在buf指向的结构中返回有关系统范围的共享内存限制和参数的信息。如果定义了_GNU_SOURCE功能测试宏,则此结构的类型为shminfo(因此,需要强制转换):
struct shminfo {
    unsigned long shmmax; /* Maximum segment size */
    unsigned long shmmin; /* Minimum segment size;
                             always 1 */
    unsigned long shmmni; /* Maximum number of segments */
    unsigned long shmseg; /* Maximum number of segments
                             that a process can attach;
                             unused within kernel */
    unsigned long shmall; /* Maximum number of pages of
                             shared memory, system-wide */
};
可以通过相同名称的/ proc文件更改shmmni,shmmax和shmall设置。有关详细信息,请参见proc(5)。
SHM_INFO(Linux-specific)
返回一个shm_info结构,该结构的字段包含有关共享内存消耗的系统资源的信息。如果定义了_GNU_SOURCE功能测试宏,则定义此结构:
struct shm_info {
    int           used_ids; /* # of currently existing
                               segments */
    unsigned long shm_tot;  /* Total number of shared
                               memory pages */
    unsigned long shm_rss;  /* # of resident shared
                               memory pages */
    unsigned long shm_swp;  /* # of swapped shared
                               memory pages */
    unsigned long swap_attempts;
                            /* Unused since Linux 2.4 */
    unsigned long swap_successes;
                            /* Unused since Linux 2.4 */
};
SHM_STAT(Linux-specific)
返回与IPC_STAT相同的shmid_ds结构。但是,shmid参数不是段标识符,而是内核内部数组的索引,该索引维护有关系统上所有共享内存段的信息。
SHM_STAT_ANY(Linux-specific, since Linux 4.17)
返回与SHM_STAT相同的shmid_ds结构。但是,不会检查shm_perm.mode的shmid读取访问权限,这意味着任何用户都可以使用此操作(就像任何用户都可以读取/ proc / sysvipc / shm以获得相同信息一样)。

调用者可以阻止或允许使用以下cmd值交换共享内存段:

SHM_LOCK(Linux-specific)
防止交换共享内存段。启用锁定后,调用者必须在要求显示的任何页面中出现故障。如果段已被锁定,则将设置IPC_STAT检索的关联数据结构中的shm_perm.mode字段的(非标准)SHM_LOCKED标志。
SHM_UNLOCK(Linux-specific)
解锁段,使其可以换出。

在2.6.10之前的内核中,只有特权进程才能使用SHM_LOCK和SHM_UNLOCK。从内核2.6.10开始,如果非特权进程的有效UID与该段的所有者或创建者UID相匹配,并且(对于SHM_LOCK)要锁定的内存量在RLIMIT_MEMLOCK资源限制内(请参阅setrlimit(2),则可以使用这些操作。 ))。

日期:2019-08-20 17:59:24 来源:oir作者:oir