文章目录

  • 一、SharedMemory 共享内存简介
  • 二、SharedMemory 基本函数
  • 1. `int shmget(key_t key, size_t size, int shmflg);`
  • 2. `void *shmat(int shmid, const void *shmaddr, int shmflg);`
  • 3. `int shmdt(const void *shmaddr);`
  • 4. `int shmctl(int shmid, int cmd, struct shmid_ds *buf);`
  • 三、SharedMemory 代码示例



一、SharedMemory 共享内存简介

共享内存是进程间通信中最简单的方式之一,不需要通过系统调用或者其它需要切入内核的过程,同时也避免了对数据的各种不必要的复制
共享内存允许两个或更多进程访问同一块内存,当一个进程改变了内容,其它所有进程都会察觉到
系统内核没有对访问共享内存进行同步,使用者必须提供自己的同步措施,常用方法是使用信号量进行同步

在 Linux 系统中,每个进程的虚拟内存是被分为许多页面的,每个进程都会维护一个从内存地址到虚拟内存页面之间的映射关系。不同的进程可以同时将同一个内存页面映射到自己的地址空间中,从而达到共享内存的目的

分配一个新的共享内存块会创建新的内存页面,只应由一个进程创建新的共享内存块,再次分配已经存在的内存块不会创建新的页面,只会返回标识该内存块的标识符

一个进程如需使用这个共享内存块,则首先需要将它绑定到自己的地址空间,这样会创建一个从进程本身虚拟地址到共享页面的映射关系

当没有进程需要使用这个共享内存块的时候,必须有一个(且只能是一个)进程负责释放这个被共享的内存页面

所有共享内存块的大小都必须是系统页面大小的整数倍,在 Linux 系统中内存页面大小是4KB,可调用 getpagesize 获取这个值

shared memory中有指针 shared memory provider_SharedMemory

二、SharedMemory 基本函数

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

用于开辟或指向一块共享内存,如果不存在指定的共享区域就创建相应的区域
key:共享内存的标识符
如果是父子关系的进程间通信的话,这个标识符用IPC_PRIVATE来代替
如果两个进程没有任何关系,所以就用ftok()算出来一个标识符(或者自己定义一个)使用了
size:字节为单位指定需要共享的内存容量
shmflg:包含9个比特的权限标志,它是这块内存的模式(mode)以及权限标识,将“模式” 和“权限标识”进行或运算,做为第三个参数,模式可取如下值:
IPC_CREAT :新建(如果已创建则返回目前共享内存的id)
IPC_EXCLIPC_CREAT:结合使用,如果已创建则返回错误
返回值:返回获得共享内存区域的 ID

2. void *shmat(int shmid, const void *shmaddr, int shmflg);

将共享内存映射到进程的地址空间中,创建完共享内存时暂时不能被任何进程访问,必须将其映射到一个进程的地址空间中才能访问
shmid: 共享内存的ID,即共享内存的标识
shmaddr:共享内存连接到进程中的起始地址
如果 shmaddrNULL,内核会把共享内存映射到系统选定的地址空间中
如果 shmaddr 不为 NULL,内核会把共享内存映射到shmaddr指定的位置
我们很少需要控制共享内存连接的地址,通常都是让系统来选择一个地址,否则就会使用程序对硬件的依赖性过高。所以一般设为 NULLshmflg:本进程对该内存的操作模式,可以由两个取值:SHM_RND为读写模式,SHM_RDONLY是只读模式,该参数通常会被设为0
返回值:返回共享内存映射到进程的起始地址( 相当于这个指针就指向此共享内存 )

3. int shmdt(const void *shmaddr);

将共享内存和当前进程分离( 仅仅是断开联系并不删除共享内存,相当于让之前的指向此共享内存的指针不再指向)
shmaddr:shmat 返回的地址

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

对这块共享内存进行控制
shmid: 共享内存的ID,即共享内存标识
cmd : 控制命令
IPC_STAT: 获取共享内存的状态:把共享内存的信息存到 shmid_ds 结构中
IPC_SET: 设置共享内存的状态:把 shmid_ds 结构中的值设置为共享内存的信息
IPC_RMID: 删除共享内存段
buf:一个结构体指针。IPC_STAT 的时候,取得的状态放在这个结构体中。如果要改变共享内存的状态,用这个结构体指定

三、SharedMemory 代码示例

// 写共享内存
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/shm.h>

#define BUFSZ 1024

int main(int argc, char *argv[])
{
    key_t key;
    int shmid;
    char *shmadd;

    key = ftok(".", 128);
    shmid = shmget(key, BUFSZ, IPC_CREAT|0666);
    shmadd = (char*)shmat(shmid, NULL, 0);
    bzero(shmadd, BUFSZ);
    strcpy(shmadd, "Hello world");
    return 0;
}


// 读共享内存
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/shm.h>

#define BUFSZ 1024

int main(int argc, char *argv[])
{
    key_t key;
    int shmid;
    char *shmadd;

    key = ftok(".", 128);
    shmid = shmget(key, BUFSZ, IPC_CREAT|0666);
    shmadd = (char*)shmat(shmid, NULL, 0);
    printf("data = [%s]\n", shmadd);
    shmdt(shmadd);
    printf("deleted shared-memory\n");
    shmctl(shmid, IPC_RMID, NULL);
    return 0;
}

shared memory中有指针 shared memory provider_共享内存_02