zoukankan      html  css  js  c++  java
  • Linux进程间通信——使用共享内存

    一、什么是共享内存

    不同进程之间共享的内存通常安排为同一段物理内存。进程可以将同一段共享内存连接到它们自己的地址空间中,所有进程都可以访问共享内存中的地址,就好像它们是由用C语言函数malloc分配的内存一样。而如果某个进程向共享内存写入数据,所做的改动将立即影响到可以访问同一段共享内存的任何其他进程。

     特点:

    1. 共享内存在各种进程间通信方式中具有最高的效率。访问共享内存区域和访问进程独有的内存区域一样快,并不需要通过系统调用或者其它需要切入内核的过程来完成。同时它也避免了对数据的各种不必要的复制。

    2. 共享内存并未提供同步机制,需要其他机制来同步对共享内存的访问,例如信号量

    二、相关函数

    它们声明在头文件 sys/shm.h中。

    1. shmget:创建共享内存

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

    第一个参数是内核中唯一的key,可以用ftok函数生成,hmget函数成功时返回一个与key相关的共享内存标识符(非负整数),用于后续的操作都是用那个返回值了。

    2. shmat:将一个共享内存段映射到调用进程的数据段中

    第一次创建完共享内存时,它还不能被任何进程访问,shmat函数的作用就是用来启动对该共享内存的访问,并把共享内存连接到当前进程的地址空间。它的原型如下:

    void *shmat(int shm_id, const void *shm_addr, int shmflg);
    第一个参数,shm_id是由shmget函数返回的共享内存标识。
    第二个参数,shm_addr指定共享内存连接到当前进程中的地址位置,通常为空,表示让系统来选择共享内存的地址。
    第三个参数,shm_flg是一组标志位,通常为0。
    调用成功时返回一个指向共享内存第一个字节的指针
    3. shmd函数
    将共享内存从当前进程中分离,注意,将共享内存分离并不是删除它,只是使该共享内存对当前进程不再可用。
    int shmdt(const void *shmaddr);

    4. shmctl

    用来控制共享内存,例如, IPC_RMID:删除共享内存段

    #include <iostream>
    #include <stdlib.h>
    #include <string.h>
    #include <sys/shm.h>
    #include <sys/ipc.h>
    #include <unistd.h>
    using namespace std;
    
    int main()
    {
      char *shmaddr;
      char *shmaddread;
      char str[]="Hello, I am a processing. 
    ";
      int shmid;
    
      key_t key = ftok(".",1);
      pid_t pid1 = fork();
      if(pid1 == -1){
        cout << "Fork error. " << endl;
        exit(1);
      }
      else if(pid1 == 0){
        //子进程1
        shmid = shmget(key,1024,IPC_CREAT | 0600);
        shmaddr = (char*)shmat(shmid, NULL, 0);
                   strcpy(shmaddr, str);
        cout << "[Writer] write: " << shmaddr << endl;
        shmdt(shmaddr);
      }
      else
      {
        //父进程
        pid_t pid2 = fork();
        if(pid2 == -1){
          cout << "Fork error. " << endl;
          exit(1);
        }
        else if(pid2 == 0){
          //子进程2
          sleep(2);
          shmid = shmget(key,1024,IPC_CREAT | 0600);
          shmaddread = (char*)shmat(shmid, NULL, 0);        
          cout << "[Reader] read: " << shmaddread << endl;
          shmdt(shmaddread);
        }
      }
      sleep(3);
      return 0;
    }

    参考链接:

    1. https://blog.csdn.net/ljianhui/article/details/10253345

    2. https://blog.ailemon.me/2018/03/19/the-theory-and-implemention-on-five-ways-for-communication-between-processings/

  • 相关阅读:
    希望走过的路成为未来的基石
    第三次个人作业--用例图设计
    第二次结对作业
    第一次结对作业
    第二次个人编程作业
    第一次个人编程作业(更新至2020.02.07)
    Springboot vue 前后分离 跨域 Activiti6 工作流 集成代码生成器 shiro权限
    springcloud 项目源码 微服务 分布式 Activiti6 工作流 vue.js html 跨域 前后分离
    spring cloud springboot 框架源码 activiti工作流 前后分离 集成代码生成器
    java代码生成器 快速开发平台 二次开发 外包项目利器 springmvc SSM后台框架源码
  • 原文地址:https://www.cnblogs.com/lfri/p/12697043.html
Copyright © 2011-2022 走看看