先调用shmget,再调用shmat。
对于每个共享内存区,内核维护如下信息结构 shmid_ds,
/* Permission flag for shmget. */
#define SHM_R 0400 /* or S_IRUGO from */
#define SHM_W 0200 /* or S_IWUGO from */
/* Flags for `shmat'. */
#define SHM_RDONLY 010000 /* attach read-only else read-write */
#define SHM_RND 020000 /* round attach address to SHMLBA */
#define SHM_REMAP 040000 /* take-over region on attach */
#define SHM_EXEC 0100000 /* execution access */
/* Commands for `shmctl'. */
#define SHM_LOCK 11 /* lock segment (root only) */
#define SHM_UNLOCK 12 /* unlock segment (root only) */
/* Data structure describing a shared memory segment. */
struct shmid_ds
{
struct ipc_perm shm_perm; /* operation permission struct */
size_t shm_segsz; /* size of segment in bytes */
__time_t shm_atime; /* time of last shmat() */
#ifndef __x86_64__
unsigned long int __glibc_reserved1;
#endif
__time_t shm_dtime; /* time of last shmdt() */
#ifndef __x86_64__
unsigned long int __glibc_reserved2;
#endif
__time_t shm_ctime; /* time of last change by shmctl() */
#ifndef __x86_64__
unsigned long int __glibc_reserved3;
#endif
__pid_t shm_cpid; /* pid of creator */
__pid_t shm_lpid; /* pid of last shmop */
shmatt_t shm_nattch; /* number of current attaches */
__syscall_ulong_t __glibc_reserved4;
__syscall_ulong_t __glibc_reserved5;
};
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; /* Last change time */
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 */
...
};
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 */
};
shmget 函数
创建一个新的共享内存区,或者访问一个已存在的共享内存区。
#include
#include
int shmget(key_t key, size_t size, int shmflg);
// 返回:若成功则为共享内存区对象,若出错为-1
返回值是一个称为
共享内存区标识符(shared memory identifier)的整数。
key:既可以是 ftok 的返回值,也可以是 IPC_PRIVATE。
size:以字节为单位指定内存区的大小。当实际操作作为创建一个新的共享内存区时,必须指定一个不为 0 的size值。如果访问一个已存在的共享内存区,那么size应为 0 。
shmflg:读写权限值的组合,可以与IPC_CREAT、IPC_EXCL。
当实际操作为创建一个新的共享内存区时,该内存区被初始化为size 字节的0。
shmat 函数
把它附接到调用进程的地址空间。
#include
#include
void *shmat(int shmid, const void *shmaddr, int shmflg);
// 返回:成功则为映射区的起始地址,出错为-1 【(void *) -1】
返回值:所指定的共享内存区在调用进程内的起始地址。
shmid:标识符。shmaddr:
shmdt 函数
当一个进程完成某个共享内存区的使用时,它可以调用 shmdt断接这个内存区。并不删除所指定的共享内存区。
#include
#include
int shmdt(const void *shmaddr);
// 返回:成功则为0,出错为-1
当一个进程终止时,它当前附接着的共享内存区都自动断接掉。
shmctl 函数
#include
#include
int shmctl(int shmid, int cmd, struct shmid_ds *buf);
// 返回:成功0,出错-1
/* Control commands for `msgctl', `semctl', and `shmctl'. */
#define IPC_RMID 0 /* Remove identifier. */
#define IPC_SET 1 /* Set `ipc_perm' options. */
#define IPC_STAT 2 /* Get `ipc_perm' options. */
IPC_RMID:从系统中删除由shmid标识的共享内存区并拆除它。
IPC_SET:给所指定的共享内存区设置其 shmid_ds 结构的以下三个成员:shm_perm.uid,shm_perm.gid和shm_perm.mode,他们的值来自buff参数指向的结构中的相应成员。shm_ctime的值也用当前时间替换。
IPC_STAT :(通过buff参数)向调用者返回所指定共享内存区当前的 shmid_ds 结构,将其保存在buf所指向的缓冲区。