进程间通信IPC---共享内存

来源:互联网 发布:js面向对象的思想 编辑:程序博客网 时间:2024/05/21 11:32

1.整体思维导图
这里写图片描述

2.详细介绍
2.1 POSIX内存映射文件
原理
Linux提供了内存映射函数mmap, 它把文件内容映射到一段内存上(准确说是虚拟内存上), 通过对这段内存的读取和修改, 实现对文件的读取和修改,mmap()系统调用使得进程之间可以通过映射一个普通的文件实现共享内存。普通文件映射到进程地址空间后,进程可以向访问内存的方式对文件进行访问,不需要其他系统调用(read,write)去操作。如果需要同步到文件里,需要调用msync().
特点:访问速度慢,因为内核为同步或异步更新到文件系统中,而内存区对象是直接操作内存的。存储量大。
生命周期:随文件,即进程重启或内核自举不后丢失,除非显示rm掉文件后丢失。

2.1.1 接口函数详解
void *mmap(void *addr, size_t length, int prot, int flags, int fd, off_t offset);

  • addr: 指向欲映射的内存起始地址,通常设为 NULL,代表让系统自动选定地址,映射成功后返回该地址。
  • length: 代表将文件中多大的部分映射到内存。
  • prot : 映射区域的保护方式。可以为以下几种方式的组合:
    PROT_EXEC 映射区域可被执行
    PROT_READ 映射区域可被读取
    PROT_WRITE 映射区域可被写入
    PROT_NONE 映射区域不能存取
  • flags : 影响映射区域的各种特性。在调用mmap()时必须要指定MAP_SHARE或 MAP_PRIVATE。
    MAP_FIXED 如果参数start所指的地址无法成功建立映射时,则放弃映射,不对地址做修正。通常不鼓励用此旗标。
    MAP_SHARED 对映射区域的写入数据会复制回文件内,而且允许其他映射该文件的进程共享。
    MAP_PRIVATE 对映射区域的写入操作会产生一个映射文件的复制,即私人的“写入时复制”(copy on write)对此区域作的任何修改都不会写回原来的文件内容。
    MAP_ANONYMOUS建立匿名映射。此时会忽略参数fd,不涉及文件,而且映射区域无法和其他进程共享。
    MAP_DENYWRITE只允许对映射区域的写入操作,其他对文件直接写入的操作将会被拒绝。
    MAP_LOCKED 将映射区域锁定住,这表示该区域不会被置换(swap)。
  • fd : 要映射到内存中的文件描述符。如果使用匿名内存映射时,即flags中设置了MAP_ANONYMOUS,fd设为-1。有些系统不支持匿名内存映射,则可以使用fopen打开/dev/zero文件,
    然后对该文件进行映射,可以同样达到匿名内存映射的效果。
  • offset:文件映射的偏移量,通常设置为0,代表从文件最前方开始对应,offset必须是PAGE_SIZE的整数倍。
  • 返回值:
    若映射成功则返回映射区的内存起始地址,否则返回MAP_FAILED(-1),错误原因存于errno 中。
    错误代码:
    EBADF 参数fd 不是有效的文件描述词
    EACCES 存取权限有误。如果是MAP_PRIVATE 情况下文件必须可读,使用MAP_SHARED则要有PROT_WRITE以及该文件要能写入。
    EINVAL 参数start、length 或offset有一个不合法。
    EAGAIN 文件被锁住,或是有太多内存被锁住。
    ENOMEM 内存不足。

int munmap( void * addr, size_t len ) ;

  • 函数说明 munmap()用来取消参数start所指的映射内存起始地址,参数length则是欲取消的内存大小。当进程结束或利用exec相关函数来执行其他程序时,映射内存会自动解除,但关闭对应的文件描述符时不会解除映射。

  • 返回值 如果解除映射成功则返回0,否则返回-1,错误原因存于errno中错误代码EINVAL

int msync ( void * addr , size_t len, int flags) ;

  • 注释:
    1、刷新变化函数msync()
    2、进程在映射空间的对共享内容的改变并不直接写回到磁盘文件中,往往在调用munmap()后才执行该操作。可以通过调用msync()函数来实现磁盘文件内容与共享内存区中的内容一致,即同步操作.

  • 说明:
    1 . 当映射区数据被修改时,内核会稍后将其更新到文件。但有时候为了确保修改能被反映到文件,可以调用 msync 函数来进行同步操作。
    2 . addr:文件映射到进程空间的地址;
    len:映射空间的大小。
    3 . 参数 flags 控制回写到文件的具体方式。MS_ASYNC 、MS_SYNC 必须指定其一。
    MS_ASYNC ,只是将写操作排队,并不等待写操作完成就返回。
    MS_SYNC ,等待写操作完成后才返回。
    MS_INVALIDATE ,作废与实际文件内容不一致缓存页,有的实现则是作废整个映射区的缓存页。后续的引用将从文件获取数据。

    4 . 返回值:成功则返回0;失败则返回-1;

2.2 POSIX共享内存对象
原理
在 /dev/shm (tmpfs的文件系统)下,创建一段共享内存,然后映射到各自的进程里。
特点:访问速度快。
生命周期:随内核,即进程重启共享内存中数据不会丢失;但是内核自举或显示调用shm_unlink或rm掉文件删除后丢失。
2.2.1 接口函数详解
int shm_open(const char *name,int oflag,mode_t mode);

  • 功能:打开或创建一个共享内存区

  • 参数:name 共享内存区的名字
    cflag 标志位
    mode 权限位
    返回值:
    成功返回0,出错返回-1

  • 注意项:
    oflag参数必须含有O_RDONLY和O_RDWR标志,还可以指定如下标志:O_CREAT,O_EXCL或O_TRUNC.
    mode参数指定权限位,它指定O_CREAT标志的前提下使用。
    shm_open的返回值是一个整数描述字,它随后用作mmap的第五个参数。

int ftruncate(int fd, off_t length);

  • 功能:改变文件大小 。
  • 参数:fd:为已打开的文件描述符。
    length:设置的大小。

  • 注意项:必须是以写入模式打开的文件。如果原来的文件件大小比参数length大,则超过的部分会被删去。

void *mmap(void *addr, size_t length, int prot, int flags, int fd, off_t offset);
同上

int shm_unlink(const char *name);

  • 功能:删除一个共享内存区

  • 参数:name:共享内存区的名字

注意项:–

2.3 SYSTEM V共享内存对象
原理:同POSIX共享内存对象

2.3.1 接口函数详解
key_t ftok( char * fname, int id );

  • 功能:系统建立IPC通讯(消息队列、信号量和共享内存)时必须指定一个ID值。通常情况下,该id值通过ftok函数得到。
  • 参数:fname:指定的文件名(已经存在的文件名)。
    id:子序号。
  • 返回值:当成功执行的时候,一个key_t值将会被返回,否则 -1 被返回。

int shmget(key_t key, size_t size, int shmflg);

  • 功能:得到一个共享内存标识符或创建一个共享内存对象并返回共享内存标识符。
  • 参数:
    key:0(IPC_PRIVATE):会建立新共享内存对象;大于0的32位整数:视参数shmflg来确定操作。通常要求此值来源于ftok返回的IPC键值。
    size:大于0的整数:新建的共享内存大小,以字节为单位;0:只获取共享内存时指定为0。
    shmflg:0:取共享内存标识符,若不存在则函数会报错。IPC_CREAT:当shmflg&IPC_CREAT为真时,如果内核中不存在键值与key相等的共享内存,则新建一个共享内存;如果存在这样的共享内存,返回此共享内存的标识符;IPC_CREAT|IPC_EXCL:如果内核中不存在键值与key相等的共享内存,则新建一个消息队列;如果存在这样的共享内存则报错。
  • 返回值:成功:返回共享内存的标识符。失败:-1,错误原因存于error中。

void *shmat(int shmid, constvoid shmaddr,int shmflg);

  • 功能:连接共享内存标识符为shmid的共享内存,连接成功后把共享内存区对象映射到调用进程的地址空间,随后可像本地空间一样访问。
  • 参数:
    msqid:共享内存标识符。
    shmaddr:指定共享内存出现在进程内存地址的什么位置,直接指定为NULL让内核自己决定一个合适的地址位置。
    shmflg:SHM_RDONLY:为只读模式,其他为读写模式。
  • 返回值:成功:附加好的共享内存地址;出错:-1,错误原因存于error中。

void shmdt(constvoid shmaddr);

  • 功能:与shmat函数相反,是用来断开与共享内存附加点的地址,禁止本进程访问此片共享内存。
  • 参数:shmaddr:连接的共享内存的起始地址。
  • 返回值:成功:0;出错:-1,错误原因存于error中。

int shmctl(int shmid, int cmd, struct shmid_ds* buf);

  • 功能:完成对共享内存的控制。
  • 参数:msqid:共享内存标识符。
    cmd:IPC_STAT:得到共享内存的状态,把共享内存的shmid_ds结构复制到buf中;
    IPC_SET:改变共享内存的状态,把buf所指的shmid_ds结构中的uid、gid、mode复制到共享内存的shmid_ds结构内;IPC_RMID:删除这片共享内存。
    buf:共享内存管理结构体。具体说明参见共享内存内核结构定义部分。
  • 返回值:成功:0;出错:-1,错误原因存于error中。

3.应用实例