Java学习者论坛

 找回密码
 立即注册

QQ登录

只需一步,快速开始

手机号码,快捷登录

恭喜Java学习者论坛(https://www.javaxxz.com)已经为数万Java学习者服务超过8年了!积累会员资料超过10000G+
成为本站VIP会员,下载本站10000G+会员资源,购买链接:点击进入购买VIP会员
JAVA高级面试进阶视频教程Java架构师系统进阶VIP课程

分布式高可用全栈开发微服务教程

Go语言视频零基础入门到精通

Java架构师3期(课件+源码)

Java开发全终端实战租房项目视频教程

SpringBoot2.X入门到高级使用教程

大数据培训第六期全套视频教程

深度学习(CNN RNN GAN)算法原理

Java亿级流量电商系统视频教程

互联网架构师视频教程

年薪50万Spark2.0从入门到精通

年薪50万!人工智能学习路线教程

年薪50万!大数据从入门到精通学习路线年薪50万!机器学习入门到精通视频教程
仿小米商城类app和小程序视频教程深度学习数据分析基础到实战最新黑马javaEE2.1就业课程从 0到JVM实战高手教程 MySQL入门到精通教程
查看: 353|回复: 0

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

[复制链接]
  • TA的每日心情
    开心
    2021-12-13 21:45
  • 签到天数: 15 天

    [LV.4]偶尔看看III

    发表于 2018-3-19 09:15:27 | 显示全部楼层 |阅读模式

      
      Linux进程IPC浅析[进程间通信SystemV共享内存]
      
       共享内存概念,概述
       共享内存的相关函数
      
      共享内存概念,概述
      共享内存区域是被多个进程共享的一部分物理内存
      多个进程都可把该共享内存映射到自己的虚拟内存空间,全部用户空间的进程若要操作共享内存。都要将其映射到自己的虚拟内存空间中。通过映射的虚拟内存空间地址去操作共享内存,从而达到进程间的数据通信
      共享内存是进程间共享数据的一种最快的方法。一个进程向共享内存区域写入了数据。共享这个内存区域的全部进程就能够立马看到当中的内容
      本身不提供同步机制,可通过信号量进行同步(用信号量进行通知)
    提升数据处理效率。一种效率最高的IPC机制
      共享内存的属性信息:
    1. [code]struct shmid_ds{
    2.     struct ipc_perm shm_perm;
    3.     size_t shm_segsz; //共享内存大小
    4.     pid_t shm_lpid; //最后一次调用系统调用的进程的pid
    5.     pid_t shm_cpid; //创建者pid
    6.     shmatt_t shm_nattch;//当前成功映射的进程的数量
    7.     time_t shm_atime; //最后一个成功映射的时间
    8.     time_t shm_dtime; //最后一个解除映射的时间
    9.     time_t shm_ctime; //最后一次改变的时间
    10.     ....;
    11. }
    复制代码
    [/code]
      共享内存的使用步骤:
    1. [code]使用shmget函数创建共享内存
    2. 使用shmat函数映射共享内存。将这段创建的共享内存映射到详细的进程虚拟内存空间中
    复制代码
    [/code]
      创建共享内存
    1. [code]#include<sys/shm.h>
    2. int shmget(key_t key,size_t size,int shmflg);
    3. 返回:假设成功。返回内核中共享内存的表示ID,假设失败,则返回-1
    4. 參数:
    5. key:用户制定的共享内存键值
    6. size_t:共享内存的大小
    7. shmflg:IPC_CREAT,IPC_EXCL等权限
    8. errno:
    9.     EINVAL(无效的内存段)
    10.     EEXIST(内存段已经存在。无法创建)
    11.     EIDRM(内存段已经被删除)
    12.     ENOENT(内存段不存在)
    13.     EACCES(权限不够)
    14.     ENOMEN(没有足够的内存来创建内存段)
    复制代码
    [/code]
      对共享内存的控制:
    1. [code]#include<sys/shm.h>
    2. int shmctl(int shmid,int cmd,struct shmid_ds *buf);
    3. 返回:成功返回0,出错返回-1
    4. 參数:
    5.     shmid:共享内存ID
    6.     buf:共享内存属性指针
    7. cmd:
    8.     IPC_STAT 获取共享内存段属性
    9.     IPC_SET 设置共享内存段属性
    10.     IPC_RMID 删除共享内存段
    11.     SHM_LOCK 锁定共享内存段页面
    12.     SHM_UNLOCK 解除共享内存段页面的锁定
    复制代码
    [/code]
      共享内存的映射和映射的解除:
    1. [code]#include<sys/shm.h>
    2. void* shmat(int shmid,char *shmaddr,int shmflag);
    3. 返回:成功返回共享内存映射到进程虚拟内存空间中的地址。失败返回-1,然后通过操作共享内存的地址来进行写操作
    4. int shmdt(char *shmaddr);
    5. 返回:假设失败,返回-1
    6. 參数:
    7.     shmid:共享内存ID
    8.     shmaddr:映射到进程虚拟内存空间的地址,建议设置为0,由系统分配
    9.     shmflg:若shmaddr设置为0,则shmflag也设置为0
    10.         SHM_RND
    11.         SHMLBA 地址为2的乘方
    12.         SHM_RDONLY 仅仅读方式链接
    13.     errno
    14.         EINVAL 无效的IPC ID值或者无效的地址
    15.         ENOMEN 没有足够内存
    16.         EACCESS 权限不够
    17.         子进程不继承父进程创建的共享内存,大家是共享的,子进程继承父进程映射的地址
    复制代码
    [/code]
      下面的代码是通过管道的形式来对共享内存实现同步,一个进程实现对共享内存的写后,通过管道通知另外一个进程去从共享内存中去读取:
    1. [code]/*
    2. * ===========================================================================
    3. *
    4. * Filename: tell.h
    5. * Description:
    6. * Version: 1.0
    7. * Created: 2017年04月16日 10时40分31秒
    8. * Revision: none
    9. * Compiler: gcc
    10. * Author: (),
    11. * Company:
    12. *
    13. * ===========================================================================
    14. */
    15. #ifndef __TELL_H_
    16. #define __TELL_H_
    17. //初始化管道
    18. extern void pipe_init();
    19. //通知管道
    20. extern void pipe_notify();
    21. //管道堵塞等待
    22. extern void pipe_wait();
    23. //销毁管道
    24. extern void pipe_destory();
    25. #endif
    复制代码
    [/code]
    1. [code]/*
    2. * ===========================================================================
    3. *
    4. * Filename: tell.c
    5. * Description:
    6. * Version: 1.0
    7. * Created: 2017年04月16日 10时42分23秒
    8. * Revision: none
    9. * Compiler: gcc
    10. * Author: (),
    11. * Company:
    12. *
    13. * ===========================================================================
    14. */
    15. #include<stdio.h>
    16. #include<stdlib.h>
    17. #include"tell.h"
    18. #include<unistd.h>
    19. #define BUFFER_SIZE 1024
    20. //管道的文件描写叙述符号
    21. static int pipe_fd[2];
    22. //初始化管道
    23. extern void pipe_init(){
    24.   if(pipe(pipe_fd) < 0){
    25.     perror("create pipe error\n");
    26.   }
    27. }
    28. //管道等待
    29. extern void pipe_wait(){
    30.   char buffer[BUFFER_SIZE];
    31.   if((read(pipe_fd[0],&buffer,sizeof(buffer))) != 0){
    32.      printf("read content:%s\n",buffer);
    33.   }
    34. }
    35. //通知管道
    36. extern void pipe_notify(){
    37.   ssize_t size;
    38.   char content[] = "notify";
    39.   if((size = write(pipe_fd[1],content,sizeof(content))) !=sizeof(content)){
    40.     perror("write error");
    41.   }
    42. }
    43. //销毁管道
    44. extern void pipe_destory(){
    45.   close(pipe_fd[0]);
    46.   close(pipe_fd[1]);
    47. }
    复制代码
    [/code]
    1. [code]/*
    2. * ===========================================================================
    3. *
    4. * Filename: shmtest.c
    5. * Description:
    6. * Version: 1.0
    7. * Created: 2017年04月16日 10时51分54秒
    8. * Revision: none
    9. * Compiler: gcc
    10. * Author: (),
    11. * Company:
    12. *
    13. * ===========================================================================
    14. */
    15. #include<stdio.h>
    16. #include<stdlib.h>
    17. #include<unistd.h>
    18. #include<string.h>
    19. #include"tell.h"
    20. #include<sys/shm.h>
    21. #define SHM_BUFFER_SIZE 1024
    22. int main(int argc,char*argv[]){
    23.   pid_t pid;
    24.   int shmid;
    25.   //创建共享内存
    26.   shmid = shmget(IPC_PRIVATE,SHM_BUFFER_SIZE,IPC_CREAT | IPC_EXCL | 0777);
    27.   if(shmid < 0){
    28.     perror("create share memory error");
    29.   }
    30.   //初始化管道
    31.   pipe_init();
    32.   if((pid = fork()) < 0){
    33.   }else if(pid > 0){
    34.     //父进程运行的时间片
    35.     //父进程进行共享内存的映射
    36.     int* shm_int_pointer = shmat(shmid,0,0);
    37.     if(shm_int_pointer == (int *)-1){
    38.       perror("error");
    39.     }
    40.     //父进程往共享内存中写数据
    41.     *shm_int_pointer = 10;
    42.     *(shm_int_pointer + 1)= 100;
    43.     *(shm_int_pointer + 2) = 1000;
    44.     //取消共享内存的映射
    45.     shmdt(shm_int_pointer);
    46.     //通知子进程
    47.     pipe_notify();
    48.     //管道进行销毁
    49.     pipe_destory();
    50.     wait(0);
    51.   }else{
    52.     //子进程运行的时间片
    53.     //子进程堵塞
    54.     pipe_wait();
    55.     int *shm_int_pointer = shmat(shmid,0,0);
    56.     if(shm_int_pointer == (int *)-1){
    57.       perror("error");
    58.       exit(1);
    59.     }
    60.     int num1 = *shm_int_pointer;
    61.     int num2 = *(shm_int_pointer+1);
    62.     int num3 = *(shm_int_pointer+2);
    63.     printf("num1:%d,num2:%d,num3:%d\n",num1,num2,num3);
    64.     shmdt(shm_int_pointer);
    65.     //删除共享内存
    66.     int shm_ctl_result = shmctl(shmid,IPC_RMID,NULL);
    67.     if(shm_ctl_result == -1){
    68.       perror("delete shmctl error");
    69.     }
    70.     pipe_destory();
    71.   }
    72.   return 0;
    73. }
    复制代码
    [/code]
      以上部分就是关于共享内存部分的相关简单的调用,代码调试过
      欢迎持续訪问博客
      
      
    回复

    使用道具 举报

    您需要登录后才可以回帖 登录 | 立即注册

    本版积分规则

    QQ|手机版|Java学习者论坛 ( 声明:本站资料整理自互联网,用于Java学习者交流学习使用,对资料版权不负任何法律责任,若有侵权请及时联系客服屏蔽删除 )

    GMT+8, 2024-5-18 00:34 , Processed in 0.382399 second(s), 37 queries .

    Powered by Discuz! X3.4

    © 2001-2017 Comsenz Inc.

    快速回复 返回顶部 返回列表