zoukankan      html  css  js  c++  java
  • Linux进程IPC浅析[进程间通信SystemV共享内存]

    Linux进程IPC浅析[进程间通信SystemV共享内存]

    • 共享内存概念,概述
    • 共享内存的相关函数

    共享内存概念,概述

    共享内存区域是被多个进程共享的一部分物理内存

    多个进程都可把该共享内存映射到自己的虚拟内存空间,全部用户空间的进程若要操作共享内存。都要将其映射到自己的虚拟内存空间中。通过映射的虚拟内存空间地址去操作共享内存,从而达到进程间的数据通信

    共享内存是进程间共享数据的一种最快的方法。一个进程向共享内存区域写入了数据。共享这个内存区域的全部进程就能够立马看到当中的内容

    本身不提供同步机制,可通过信号量进行同步(用信号量进行通知)
    提升数据处理效率。一种效率最高的IPC机制

    共享内存的属性信息:

    struct shmid_ds{
        struct ipc_perm shm_perm;
        size_t shm_segsz; //共享内存大小
        pid_t shm_lpid; //最后一次调用系统调用的进程的pid
        pid_t shm_cpid; //创建者pid
        shmatt_t shm_nattch;//当前成功映射的进程的数量
        time_t shm_atime; //最后一个成功映射的时间
        time_t shm_dtime; //最后一个解除映射的时间
        time_t shm_ctime; //最后一次改变的时间
        ....;
    }
    

    共享内存的使用步骤:

    使用shmget函数创建共享内存
    使用shmat函数映射共享内存。将这段创建的共享内存映射到详细的进程虚拟内存空间中
    

    创建共享内存

    #include<sys/shm.h>
    int shmget(key_t key,size_t size,int shmflg);
    返回:假设成功。返回内核中共享内存的表示ID,假设失败,则返回-1
    
    參数:
    key:用户制定的共享内存键值
    size_t:共享内存的大小
    shmflg:IPC_CREAT,IPC_EXCL等权限
    errno:
        EINVAL(无效的内存段)
        EEXIST(内存段已经存在。无法创建)
        EIDRM(内存段已经被删除)
        ENOENT(内存段不存在)
        EACCES(权限不够)
        ENOMEN(没有足够的内存来创建内存段)
    

    对共享内存的控制:

    #include<sys/shm.h>
    int shmctl(int shmid,int cmd,struct shmid_ds *buf);
    返回:成功返回0,出错返回-1
    參数:
        shmid:共享内存ID
        buf:共享内存属性指针
    cmd:
        IPC_STAT 获取共享内存段属性
        IPC_SET 设置共享内存段属性
        IPC_RMID 删除共享内存段
        SHM_LOCK 锁定共享内存段页面 
        SHM_UNLOCK 解除共享内存段页面的锁定
    

    共享内存的映射和映射的解除:

    #include<sys/shm.h>
    void* shmat(int shmid,char *shmaddr,int shmflag);
    返回:成功返回共享内存映射到进程虚拟内存空间中的地址。失败返回-1,然后通过操作共享内存的地址来进行写操作
    int shmdt(char *shmaddr);
    返回:假设失败,返回-1
    參数:
        shmid:共享内存ID
        shmaddr:映射到进程虚拟内存空间的地址,建议设置为0,由系统分配
        shmflg:若shmaddr设置为0,则shmflag也设置为0
            SHM_RND
            SHMLBA 地址为2的乘方
            SHM_RDONLY 仅仅读方式链接
        errno
            EINVAL 无效的IPC ID值或者无效的地址
            ENOMEN 没有足够内存
            EACCESS 权限不够
            子进程不继承父进程创建的共享内存,大家是共享的,子进程继承父进程映射的地址
    

    下面的代码是通过管道的形式来对共享内存实现同步,一个进程实现对共享内存的写后,通过管道通知另外一个进程去从共享内存中去读取:

    /*
     * ===========================================================================
     *
     *       Filename:  tell.h
     *    Description:  
     *        Version:  1.0
     *        Created:  2017年04月16日 10时40分31秒
     *       Revision:  none
     *       Compiler:  gcc
     *         Author:   (), 
     *        Company:  
     *
     * ===========================================================================
     */
    
    #ifndef __TELL_H_
    #define __TELL_H_
    //初始化管道
    extern void pipe_init();
    //通知管道
    extern void pipe_notify();
    //管道堵塞等待
    extern void pipe_wait();
    //销毁管道
    extern void pipe_destory();
    
    #endif
    /*
     * ===========================================================================
     *
     *       Filename:  tell.c
     *    Description:  
     *        Version:  1.0
     *        Created:  2017年04月16日 10时42分23秒
     *       Revision:  none
     *       Compiler:  gcc
     *         Author:   (), 
     *        Company:  
     *
     * ===========================================================================
     */
    
    #include<stdio.h>
    #include<stdlib.h>
    #include"tell.h"
    #include<unistd.h>
    
    
    #define BUFFER_SIZE 1024
    //管道的文件描写叙述符号
    static int pipe_fd[2];
    
    //初始化管道
    extern void pipe_init(){
      if(pipe(pipe_fd) < 0){
        perror("create pipe error
    ");
      }
    }
    
    //管道等待
    extern void pipe_wait(){
      char buffer[BUFFER_SIZE];
      if((read(pipe_fd[0],&buffer,sizeof(buffer))) != 0){
         printf("read content:%s
    ",buffer);
      }
    }
    
    //通知管道
    extern void pipe_notify(){
      ssize_t size;
      char content[] = "notify";
      if((size = write(pipe_fd[1],content,sizeof(content))) !=sizeof(content)){
        perror("write error");
      }
    }
    
    //销毁管道
    extern void pipe_destory(){
      close(pipe_fd[0]);
      close(pipe_fd[1]);
    }
    /*
     * ===========================================================================
     *
     *       Filename:  shmtest.c
     *    Description:  
     *        Version:  1.0
     *        Created:  2017年04月16日 10时51分54秒
     *       Revision:  none
     *       Compiler:  gcc
     *         Author:   (), 
     *        Company:  
     *
     * ===========================================================================
     */
    #include<stdio.h>
    #include<stdlib.h>
    #include<unistd.h>
    #include<string.h>
    #include"tell.h"
    #include<sys/shm.h>
    
    #define SHM_BUFFER_SIZE 1024
    int main(int argc,char*argv[]){
      pid_t pid;
      int shmid;
      //创建共享内存
      shmid = shmget(IPC_PRIVATE,SHM_BUFFER_SIZE,IPC_CREAT | IPC_EXCL | 0777);
      if(shmid < 0){
        perror("create share memory error");
      }
      //初始化管道
      pipe_init();
      if((pid = fork()) < 0){
    
      }else if(pid > 0){
        //父进程运行的时间片
        //父进程进行共享内存的映射
        int* shm_int_pointer = shmat(shmid,0,0);
        if(shm_int_pointer == (int *)-1){
          perror("error");
        }
        //父进程往共享内存中写数据
        *shm_int_pointer = 10;
        *(shm_int_pointer + 1)= 100;
        *(shm_int_pointer + 2) = 1000;
    
        //取消共享内存的映射
        shmdt(shm_int_pointer);
        //通知子进程
        pipe_notify();
        //管道进行销毁
        pipe_destory();
        wait(0);
      }else{
        //子进程运行的时间片
        //子进程堵塞
        pipe_wait();
        int *shm_int_pointer = shmat(shmid,0,0);
        if(shm_int_pointer == (int *)-1){
          perror("error");
          exit(1);
        }
        int num1 = *shm_int_pointer;
        int num2 = *(shm_int_pointer+1);
        int num3 = *(shm_int_pointer+2);
        printf("num1:%d,num2:%d,num3:%d
    ",num1,num2,num3);
    
        shmdt(shm_int_pointer);
        //删除共享内存
        int shm_ctl_result = shmctl(shmid,IPC_RMID,NULL);
        if(shm_ctl_result == -1){
          perror("delete shmctl error");
        }
        pipe_destory();
      }
    
    
      return 0;
    }

    以上部分就是关于共享内存部分的相关简单的调用,代码调试过

    欢迎持续訪问博客

  • 相关阅读:
    jquery实现 图片延迟加载
    JSON在PHP中的应用
    【SAS NOTES】proc corr 检验变量相关性
    【SAS NOTES】proc freq 检验两分类变量
    【sas notes】proc sgplot拟合曲线
    【sas notes】proc sgplot折线图
    【sas notes】proc sgplot
    【SAS NOTES】proc reg 单变量线性回归
    【SAS NOTES】proc sgplot散点图
    【sas notes】sas9.2安装
  • 原文地址:https://www.cnblogs.com/zhchoutai/p/8591733.html
Copyright © 2011-2022 走看看