1.什么是共享内存?

  共享内存就是允许两个不相关的进程访问同一个逻辑内存。共享内存是在两个正在运行的进程之间共享和传递数据的一种非常有效的方式。不同进程之间共享的内存通常安排为同一段物理内存。进程可以将同一段共享内存连接到它们自己的地址空间中,所有进程都可以访问共享内存中的地址,就好像它们是由用C语言函数malloc分配的内存一样。而如果某个进程向共享内存写入数据,所做的改动将立即影响到可以访问同一段共享内存的任何其他进程。共享内存并未提供同步机制,也就是说,在第一个进程结束对共享内存的写操作之前,并无自动机制可以阻止第二个进程开始对它进行读取。所以我们通常需要用其他的机制来同步对共享内存的访问

2.如何使用共享内存?

2.1 对一个进程/线程使用shmget()分配内存区域。(进程使用shmget申请一个共享内存)
2.2使用shmat()放置一个或多个进程/线程在共享内存中,也可以用shmctl()来获取信息或者控制共享区域。(在本线程中获取共享内存的地址)
2.3 使用shmdt()从共享区域中分离。
2.4 使用shmctl()解除分配空间

2.1shmget()

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

第一个参数,与信号量的semget函数一样,程序需要提供一个参数key(非0整数),它有效地为共享内存段命名,shmget函数成功时返回一个与key相关的共享内存标识符(非负整数),用于后续的共享内存函数。调用失败返回-1.

如果key已经存在,会分配失败。

key值可以通过ftok()函数获取;

不相关的进程可以通过该函数的返回值访问同一共享内存,它代表程序可能要使用的某个资源,程序对所有共享内存的访问都是间接的,程序先通过调用shmget函数并提供一个键,再由系统生成一个相应的共享内存标识符(shmget函数的返回值),只有shmget函数才直接使用信号量键,所有其他的信号量函数使用由semget函数返回的信号量标识符。

第二个参数,size以字节为单位指定需要共享的内存容量;在linux4.0中size最大值为4G,超过该值会失败。

第三个参数,shmflg是权限标志,它的作用与open函数的mode参数一样,如果要想在key标识的共享内存不存在时,创建它的话,可以与IPC_CREAT做或操作。共享内存的权限标志与文件的读写权限一样,举例来说,0644,它表示允许一个进程创建的共享内存被内存创建者所拥有的进程向共享内存读取和写入数据,同时其他用户创建的进程只能读取共享内存。

2.2shmat函数

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

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

void *shmat(int shm_id, const void *shm_addr, int shmflg);

第一个参数,shm_id是由shmget函数返回的共享内存标识。

第二个参数,shm_addr指定共享内存连接到当前进程中的地址位置,通常为空,表示让系统来选择共享内存的地址。

第三个参数,shm_flg是一组标志位,通常为0。

调用成功时返回一个指向共享内存第一个字节的指针,如果调用失败返回-1.

2.3shmdt函数

该函数用于将共享内存从当前进程中分离。注意,将共享内存分离并不是删除它,只是使该共享内存对当前进程不再可用。它的原型如下

int shmdt(const void *shmaddr);

参数shmaddr是shmat函数返回的地址指针,调用成功时返回0,失败时返回-1.

2.4shmctl函数

与信号量的semctl函数一样,用来控制共享内存,它的原型如下:

int shmctl(int shm_id, int command, struct shmid_ds *buf);

第一个参数,shm_id是shmget函数返回的共享内存标识符。

第二个参数,command是要采取的操作,它可以取下面的三个值 :

IPC_STAT:把shmid_ds结构中的数据设置为共享内存的当前关联值,即用共享内存的当前关联值覆盖shmid_ds的值。

IPC_SET:如果进程有足够的权限,就把共享内存的当前关联值设置为shmid_ds结构中给出的值

IPC_RMID:删除共享内存段

第三个参数,buf是一个结构指针,它指向共享内存模式和访问权限的结构

3.实例

//shmread.c

#include <unistd.h> 
#include <stdlib.h> 
#include <stdio.h> 
#include <sys/shm.h> 
#include "shmdata.h"

int main() 

  int running = 1;//程序是否继续运行的标志 
  void *shm = NULL;//分配的共享内存的原始首地址 
  struct shared_use_st *shared;//指向shm 
  int shmid;//共享内存标识符 
  shmid = shmget((key_t)1234, sizeof(struct shared_use_st), 0666|IPC_CREAT);   //创建共享内存

  if(shmid == -1) 
  { 
    fprintf(stderr, "shmget failed\n"); 
    exit(EXIT_FAILURE); 
  }

  shm = shmat(shmid, 0, 0);        //将共享内存连接到当前进程的地址空间 
  if(shm == (void*)-1) 
  { 
    fprintf(stderr, "shmat failed\n"); 
    exit(EXIT_FAILURE); 
  } 
  printf("\nMemory attached at %X\n", (int)shm); 
  //设置共享内存 
  shared = (struct shared_use_st*)shm; 
  shared->written = 0; 
  while(running)//读取共享内存中的数据 
  { 
    //没有进程向共享内存定数据有数据可读取 
    if(shared->written != 0) 
    { 
      printf("You wrote: %s", shared->text); 
      sleep(rand() % 3); 
       //读取完数据,设置written使共享内存段可写 
      shared->written = 0; 
      //输入了end,退出循环(程序)

      if(strncmp(shared->text, "end", 3) == 0) 
      running = 0; 
    } 
    else//有其他进程在写数据,不能读取数据 
    sleep(1); 
  } 
  //把共享内存从当前进程中分离 
  if(shmdt(shm) == -1) 
  { 
    fprintf(stderr, "shmdt failed\n"); 
    exit(EXIT_FAILURE); 
  } 
  //删除共享内存 
  if(shmctl(shmid, IPC_RMID, 0) == -1) 
  { 
    fprintf(stderr, "shmctl(IPC_RMID) failed\n"); 
    exit(EXIT_FAILURE); 
  } 
  exit(EXIT_SUCCESS); 
}

//shmwrite.c

#include <unistd.h> 
#include <stdlib.h> 
#include <stdio.h> 
#include <string.h> 
#include <sys/shm.h> 
#include "shmdata.h"

int main() 

  int running = 1; 
  void *shm = NULL; 
  struct shared_use_st *shared = NULL; 
  char buffer[BUFSIZ + 1];//用于保存输入的文本 
  int shmid; 
  //创建共享内存 
  shmid = shmget((key_t)1234, sizeof(struct shared_use_st), 0666|IPC_CREAT); 
  if(shmid == -1) 
  { 
    fprintf(stderr, "shmget failed\n"); 
    exit(EXIT_FAILURE); 
  } 
  //将共享内存连接到当前进程的地址空间 
  shm = shmat(shmid, (void*)0, 0); 
  if(shm == (void*)-1) 
  { 
    fprintf(stderr, "shmat failed\n"); 
    exit(EXIT_FAILURE); 
  } 
  printf("Memory attached at %X\n", (int)shm); 
  //设置共享内存 
  shared = (struct shared_use_st*)shm; 
  while(running)//向共享内存中写数据 
  { 
    //数据还没有被读取,则等待数据被读取,不能向共享内存中写入文本 
    while(shared->written == 1) 
    { 
      sleep(1); 
      printf("Waiting...\n"); 
    } 
    //向共享内存中写入数据

    printf("Enter some text: "); 
    fgets(buffer, BUFSIZ, stdin); 
    strncpy(shared->text, buffer, TEXT_SZ); 
    //写完数据,设置written使共享内存段可读 
    shared->written = 1; 
    //输入了end,退出循环(程序) 
    if(strncmp(buffer, "end", 3) == 0) 
    running = 0; 
  } 
  //把共享内存从当前进程中分离 
  if(shmdt(shm) == -1) 
  {
    fprintf(stderr, "shmdt failed\n"); 
    exit(EXIT_FAILURE); 
  } 
  sleep(2); 
  exit(EXIT_SUCCESS); 

}

//shmdata.h

#ifndef _SHMDATA_H_HEADER 
#define _SHMDATA_H_HEADER

#define TEXT_SZ 2048

struct shared_use_st 

  int written;//作为一个标志,非0:表示可读,0表示可写 
  char text[TEXT_SZ];//记录写入和读取的文本 
};

#endif

程序的编译运行

[wss@localhost shareMemery]$ls
shmdata.h shmread.c shmwrite.c

[wss@localhost shareMemery]$gcc shmread.c -o read
[wss@localhost shareMemery]$gcc shmwrite.c -o write
[wss@localhost shareMemery]$ls
read shmdata.h shmread.c shmwrite.c write

在console1运行write

[wss@localhost shareMemery]$./write 
Memory attached at B77C0000
Enter some text: Hello share Memery!
Waiting...
Waiting...
Enter some text: have a GOOD day!
Waiting...
Waiting...
Enter some text: end
[wss@localhost shareMemery]$

在console2运行read

[wss@localhost shareMemery]$./read

Memory attached at B76FA000
You wrote: Hello share Memery!
You wrote: have a GOOD day!
You wrote: end
[wss@localhost shareMemery]$

转载自:https://www.cnblogs.com/thinkinglife/p/5492913.html

IPC--进程间通信三(共享内存)相关推荐

  1. Linux IPC进程间通信(三):信号量

    系列文章: Linux IPC进程间通信(一):管道 Linux IPC进程间通信(二):共享内存 Linux IPC进程间通信(三):信号量 Linux IPC进程间通信(四):消息队列 文章目录 ...

  2. linux 共享内存_linux进程间通信----IPC篇(一)----共享内存初识篇

    先给自己打个广告,本人的微信公众号正式上线了,搜索:张笑生的地盘,主要关注嵌入式软件开发,股票基金定投,足球等等,希望大家多多关注,有问题可以直接留言给我,一定尽心尽力回答大家的问题 一 what 所 ...

  3. [转]Linux 进程间通信:共享内存

    (上) 级别: 初级 郑彦兴 (mlinux@163.com), 国防科大攻读博士学位 2003 年 5 月 01 日 共享内存可以说是最有用的进程间通信方式,也是最快的IPC形式.两个不同进程A.B ...

  4. 进程间通信:共享内存概念及代码

    前言 接下讨论的IPC机制,它们最初由System V版本的Unix引入.由于这些机制都出现在同一个版本中并且有着相似的编程接口,所以它们被称为System V IPC机制.接下来的内容包括: 信号量 ...

  5. 进程间通信之-共享内存Shared Memory--linux内核剖析(十一)

    共享内存 共享内存是进程间通信中最简单的方式之中的一个. 共享内存是系统出于多个进程之间通讯的考虑,而预留的的一块内存区. 共享内存同意两个或很多其他进程訪问同一块内存,就如同 malloc() 函数 ...

  6. 进程间通信之共享内存

    共享内存是被多个进程共享的一部分物理内存.共享内存是进程间共享数据的一种最快的方法,一个进程向共享内存区域写入了数据,共享这个内存区域的所有进程就可以立刻看到其中的内容. 共享内存实现分两个步骤: 1 ...

  7. Linux(信号,进程间通信)共享内存,信号量,消息队列

    信号(signal) 1.1 什么是信号? 信号是在软件层次上对中断机制的一种模拟,是一种异步通信方式 1.2 信号的来源 硬件 [1] 用户在终端按下某些键时,终端驱动程序会发送信号给前台进程 ct ...

  8. Linux——进程间通信(共享内存shm)笔记

    文章目录 前言 一.共享内存的通信原理 二.共享内存函数 1.共享内存实现步骤 2.函数的说明 1.shmget( )函数 2.shmat( )函数 3.shmdt( )函数 三.代码示例: 执行结果 ...

  9. Linux进程间通信:共享内存mmap、xsi和posix

    前言 本文主要说明在Linux环境上如何使用共享内存.阅读本文可以帮你解决以下问题: 什么是共享内存和为什么要有共享内存? 如何使用mmap进行共享内存? 如何使用XSI共享内存? 如何使用POSIX ...

  10. Linux——进程间通信(共享内存【mmap实现+系统V】)

    共享内存 共享内存可以说是最有用的进程间通信方式,也是最快的IPC形式,两个不同的进程A.B共享内存的意思就是:同一块物理内存被映射到进程A.B各自的进程地址空间,进程A可以同时看到进程B对共享内存中 ...

最新文章

  1. [C#]ASP.NET MVC 3 在线学习资料
  2. 第六讲:Obj-C 内存管理4 - 自动释放池
  3. 东北考生到南方学计算机,为啥东北考生都想去南方,而南方学生很少考东北,看看他们怎么说...
  4. php http请求xml数据,使用php从HTTP POST请求中检索XML
  5. c语言语音控制游戏文献,C语言课程设计-基于C语言推箱子游戏设计-毕业论文文献.doc...
  6. STM32之RTC原理
  7. 8_less中的内置函数
  8. 为什么我的modbus tcp server只能连一个client_TCP 协议概览
  9. C++ 处理异常相关
  10. bash:pip:找不到命令
  11. 看了去年这些最热的木马、病毒和电信诈骗,感觉今年不会被骗了
  12. sp485ee 芯片调试,RE DE 一直上拉故障
  13. android手表密码忘了咋办,moto 360手表通过Android 5.0系统自动解锁手机教程
  14. Respon.WriteFile 下载文件
  15. KindEditor实现WORD粘贴图片自动上传
  16. Electron中主进程和渲染进程之间的通信
  17. 学好c语言对php的帮助,学好c语言可以干什么?
  18. 少年时期最喜欢的那些电视剧
  19. 正态分布为何如此重要?
  20. RK3399 ,64位,Ubuntu16.04系统安装ROS-kinetic方法总结

热门文章

  1. 架构选型,究竟啥时候选redis?
  2. 在微信小程序中引入 Iconfont 阿里巴巴图标库
  3. 【C语言】创建一个函数,将输入的2个数排序
  4. C#LeetCode刷题之#860-柠檬水找零(Lemonade Change)
  5. C#LeetCode刷题之#206-反转链表(Reverse Linked List)
  6. 敏捷开发 看板_什么是看板? 定义的敏捷方法论,以及如何将其用于您的软件开发团队
  7. rabbitmq异步_在Node.js中使用RabbitMQ和Tortoise进行异步消息传递
  8. 所代币代币_代币网络效应
  9. 尚学堂java 参考答案 第九章
  10. 离线安装python环境