共享内存时IPC形式中最快的一种。
POSIX 共享内存
posix.1提供了两种在无亲缘关系的进程间共享内存的方式
(1)内存映射文件:由open函数打开一个文件,由mmap函数把得到的描述符映射到当前进程地址空间中。
(2)共享内存区对象:由shm_open打开一个Posix.1 IPC名字(通常是文件系统中的一个路径名),所返回的描述符由mmap函数映射到当前进程地址空间。
posix的消息队列和信号量都是一次调用直接返回,mq_open返回mqd_t值,sem_open返回sem_t值的指针,而posix的共享内存却需要先shm_open(或者open)然后再mmap,这是因为posix在发明自己的共享内存形式时,已经存在mmap...
/* shm_open, shm_unlink - create/open or unlink POSIX shared memory objects */ #include <sys/mman.h> #include <sys/stat.h> /* For mode constants */ #include <fcntl.h> /* For O_* constants */ int shm_open(const char *name, int oflag, mode_t mode); int shm_unlink(const char *name); /* mmap, munmap - map or unmap files or devices into memory */ #include <sys/mman.h> void *mmap(void *addr, size_t length, int prot, int flags, int fd, off_t offset); int munmap(void *addr, size_t length); /* truncate, ftruncate - truncate a file to a specified length */ #include <unistd.h> #include <sys/types.h> int truncate(const char *path, off_t length); int ftruncate(int fd, off_t length); Link with -lrt.
注:可以调用ftruncate来修改共享内存区的大小
System V共享内存
/* shmget - allocates a System V shared memory segment */ #include <sys/ipc.h> #include <sys/shm.h> int shmget(key_t key, size_t size, int shmflg); /* shmat, shmdt - System V shared memory operations */ #include <sys/types.h> #include <sys/shm.h> void *shmat(int shmid, const void *shmaddr, int shmflg); int shmdt(const void *shmaddr); /* shmctl - System V shared memory control */ #include <sys/ipc.h> #include <sys/shm.h> int shmctl(int shmid, int cmd, struct shmid_ds *buf); 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 */ };
注:shmctl的cmd可以取值如下:
IPC_RMID: 删除指定共享内存区
IPC_SET: 支持设置指定共享内存区的 shmid_ds结构体中的 shm_prem.uid, shm_prem.gid 和 shm_prem.mode
IPC_STAT: 返回指定共享内存区的shmid_ds 结构
System V 共享内存区的限制
Posix 共享内存和System V共享内存的区别
Posix共享内存区对象的大小可在任何时刻通过调用ftruncate修改,而System V共享内存的大小是在调用shmget创建时固定下来的。