在这里插入图片描述

博客内容:共享内存



一、认识共享内存结构

共享内存

共享内存指 (shared memory)在多处理器的计算机系统中,可以被不同中央处理器(CPU)访问的大容量内存。由于多个CPU需要快速访问存储器,这样就要对存储器进行缓存(Cache)。任何一个缓存的数据被更新后,由于其他处理器也可能要存取,共享内存就需要立即更新,否则不同的处理器可能用到不同的数据。共享内存是 Unix下的多进程之间的通信方法 ,这种方法通常用于一个程序的多进程间通信,实际上多个程序间也可以通过共享内存来传递信息。

在这里插入图片描述
解释比较官方,对于进程来说就是PCB,内存描述符(mm_struct)、页表,还有内存之间的关系。简单的描述后就是以下这样的方式。对于内存描述符类似于文件描述符。共享内存是为了让不同的进程实现通信,就必须先让不同的进程来看见同一份资源
在这里插入图片描述

二、如何创建共享内存?

1.创建共享内存

使用共享内存需要知道这些接口,创建函数接口

  #include <sys/ipc.h>
  #include <sys/shm.h>
  int shmget(key_t key, size_t size, int shmflg);

共享内存是哪块,有多大,权限设置。第一个参数就是对于内存位置来表示内存的key。ftok函数就是采用路径和项目名来生成一个不易于冲突的一个key值。

 #include <sys/types.h>
  #include <sys/ipc.h>

  key_t ftok(const char *pathname, int proj_id);

第二个参数就是设置大小。对于后面第3个参数shmflg就是设置权限,权限和文件操作的权限采用的都是位图的数据结构来表示。

2.关联进程,取消进程

共享内存的创建完成后还需要让进程看见,需要将进程与内存关联在一起,摩天大厦也需要和自己挂钩才是自己的。所以就有函数shmat、shmdt。


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

       int shmdt(const void *shmaddr);

分别实现对于进程的关联和去关联。关联同一块内需要同样的key才能看见同一块内存。shmat第二个参数一般设置为null,函数会自己找到合适的地址。函数使用时与C语言的malloc类似都需要进行内存的一个转换,shmdt去关联时函数需要传入的是空间地址。就是shmat的返回值。在shmat与shmat之间就是通信的内容。

3.释放共享内存

共享内存是一套类似于文件描述符的规则,它不会随着进程而销毁,它跟随的是OS。所以在使用完后还需要使用函数进行销毁内存空间。使用函数进行空间释放后对于需要传输的是shmid就是使用函数shmget后的返回值,第二个参数就是命令IPC_RMID ,第3个参数一般设置为null。

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

三、代码示例

创建一个共享内存,实现通信 “i am process A”

#include <stdio.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/shm.h>
#include <string.h>

#define SHM_SIZE 4096

int main()
{
    key_t key = ftok(".", 'a');
    int shmid = shmget(key, SHM_SIZE, IPC_CREAT | 0666);
    char *shmaddr = (char *) shmat(shmid, NULL, 0);

    pid_t pid = fork();
    if (pid < 0) {
        printf("Fork Error\n");
        return -1;
    } else if (pid == 0) {  // 子进程
        char *data = "i am process A";
        memcpy(shmaddr, data, strlen(data));
    } else {  // 父进程
        usleep(100000);  // 等待子进程写入数据
        printf("%s\n", shmaddr);
        shmdt(shmaddr);
        shmctl(shmid, IPC_RMID, NULL);
    }

    return 0;
}


总结

需要注意的就是函数的返回值需要进行判断。在通信时使用是字节流通信。相关查询命令

		ipcs -m//查询共享内存
		ipcs -q//消息队列
		ipcs -s         //查看信号量对象
       ipcrm -Q key :根据键值key,删除指定的消息对列

        ipcrm -q id     :根据ID,删除指定的消息对列

        ipcrm -M key :根据键值key,删除指定的共享内存

        ipcrm -m id     :根据ID,删除指定的共享内存

        ipcrm -S key :根据键值key,删除指定的信号量

        ipcrm -s id     :根据ID,删除指定的信号量

Logo

更多推荐