先調用shmget,再調用shmat。
對於每個共享內存區,內核維護如下信息結構 shmid_ds,<sys/shm.h>
/* Permission flag for shmget. */
#define SHM_R 0400 /* or S_IRUGO from <linux/stat.h> */
#define SHM_W 0200 /* or S_IWUGO from <linux/stat.h> */
/* 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 <sys/ipc.h>
#include <sys/shm.h>
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 <sys/types.h>
#include <sys/shm.h>
void *shmat(int shmid, const void *shmaddr, int shmflg);
// 返回:成功則爲映射區的起始地址,出錯爲-1 【(void *) -1】
返回值:所指定的共享內存區在調用進程內的起始地址。
shmid:標識符。shmaddr:
- 如果shmaddr是一個空指針,那麼系統替調用者選擇地址。(可移植性最好)
- 如果shmaddr 非空,那麼返回地址取決於調用者是否給flag 參數指定了 SHM_RND 值。
- 如果沒有指定SHM_RND,那麼相應的共享內存區附接到由shmaddr參數指定的地址。
- 如果過指定了SHM_RND,那麼相應的共享內存區附接到由shmaddr參數指定的地址向下舍入一個SHMLBA常值。LBA代表“低端邊界地址”(lower boundary Address)。
shmdt 函數
當一個進程完成某個共享內存區的使用時,它可以調用 shmdt斷接這個內存區。並不刪除所指定的共享內存區。
#include <sys/types.h>
#include <sys/shm.h>
int shmdt(const void *shmaddr);
// 返回:成功則爲0,出錯爲-1
當一個進程終止時,它當前附接着的共享內存區都自動斷接掉。
shmctl 函數
#include <sys/ipc.h>
#include <sys/shm.h>
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所指向的緩衝區。