Linux IPC 共享内存

共享内存时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创建时固定下来的。

原文地址:https://www.cnblogs.com/xiaokuang/p/4629232.html