共享内存是UNIX提供的进程间通信手段中速度最快的一种,也是最快的IPC形式。为什么是最快的呢,因为数据不需要在客户进程和服务器进程之间复制,所以是最快的一种IPC。这是虚存中由多个进程共享的一个公共内存块。

两个不同进程A、B共享内存的意思是,同一块物理内存被映射到进程A、B各自的进程地址空间。进程A可以即时看到进程B对共享内存中数据的更新,反之亦然。

如果服务器进程正在将数据放入到共享存储区,则在它做完这一操作之前,客户进程不应当去取这些数据。通常信号量用于同步共享存储访问。

由于共享内存是通过映射到同一块物理内存后进行的通信,因此肯定需要映射到内存的函数和解除映射的函数,主要有以下几种

#define SHMAT       21//空间映射:把上面打开的内存区域连接到用户的进程空间中
#define SHMDT       22//解除映射:将共享内存从当前进程中分离
#define SHMGET      23//创建打开一个内存区域
#define SHMCTL      24//内存区域的控制:包括初始化和删除内存区域。

注意:共享内存通信本身没有提供同步机制,如果同时被多个进程进行映射和写操作,会导致破坏该内存空间的内容。因此在实际应用过程中,需要通过其他的机制来同步对共享内存的访问。比如信号量。

内核为每个共享存储段维护着一个结构,该结构至少要为每个共享存储段包含以下成员:

struct shmid_ds
{struct ipc_perm shm_perm; //ipc结构体size_t shm_segsz;  //请求的sizepid_t shm_lpid;   //0pid_t shm_cpid;   //创建者pidshmatt_t shm_nattch; //当前挂载数time_t shm_atime;  //0time_t shm_dtime; //0time_t shm_ctime;  //设置为当前时间
};

1.调用的第一个函数为shmget:

#include<sys/shm.h>
int shmget(key_t key,size_t size,int flag);
//key是创建共享内存id的唯一标识符,size为共享存储段的长度,以字节为单位,通常将其向上取为系统页长的整数倍。如果不是整页,则最后剩余部分是不可用的。flag表示相应的权限位。

2.shmctl函数对共享内存段执行多种操作

#include<sys/shm.h>
int shmctl(int shmid,int cmd,struct shmid_ds *buf);
//IPC_RMID:从系统中删除该共享存储段。

3.一旦创建了共享存储段,进程就可调用shmat将其连接到它的地址空间中。

void *shmat(int shmid,const void* addr,int flag);
//返回若成功,返回指向共享存储段的指针,出错返回-1
//如果成功执行,那么内核将使与该共享存储段相关的shmid_ds结构中的shm_nattch计数器值加1;当对共享存储段的操作已经结束时,则调用shmat与该段分离。这里并没有从系统中删除相关的数据结构,该标识符和ipc数据结构仍然存在。
int shmdt(const void* addr);  //为挂载时的addr
//如果调用成功,则使与该共享存储段相关的shmid_ds结构中的shm_nattch计数器值减1

具体代码实现:

//comm.h
#ifndef _COMM_H_
#define _COMM_H_
#include<stdio.h>
#include<sys/types.h>
#include<sys/ipc.h>
#include<sys/shm.h>#define PATHNAME "."
#define PROJ_ID 0X6667int CreateShm(int size);
int GetShm(int size);int destroyShm(int shmid);#endif   //_COMM_H_
//comm.c
#include"comm.h"int CommShm(int size,int flags)
{key_t key = ftok(PATHNAME,PROJ_ID);if(key < 0){perror("ftok");return -1;}int shmid = shmget(key,size,flags); if(shmid < 0){perror("shmget");return -2;}return shmid;
}int CreateShm(int size)
{return CommShm(size,IPC_CREAT|IPC_EXCL|0666);
}
int GetShm(int size)
{return CommShm(size,IPC_CREAT);
}
int destroyShm(int shmid)
{if(shmctl(shmid,IPC_RMID,NULL) < 0){perror("shmctl");return -1;}return 0;
}
//server.c
#include"comm.h"int main()
{int shmid = CreateShm(4096);
//  printf("hello server!\n");char *addr = shmat(shmid,NULL,0);if(addr == NULL){return 1;}int i = 0;char s = 'a';while(1){addr[i] = s;s++;}addr[i] = 0;sleep(4);shmdt(addr);printf("shm quit!\n");return 0;
}
//client.c
#include"comm.h"int main()
{int shmid = GetShm(4096);//printf("hello client!\n");char *addr = shmat(shmid,NULL,0);if(addr == NULL)return 2;printf("%s",addr);sleep(10);shmdt(addr);    printf("shm quit!\n");return 0;
}

运行结果:

[Linux]共享内存相关推荐

  1. linux的共享内存,linux共享内存实际在哪里?

    我只想知道共享内存驻留在Linux系统中的位置?它在物理内存还是虚拟内存中?linux共享内存实际在哪里? 我知道有关进程的虚拟内存发送信箱,他们从不同的工艺处理和流程没有看到对方的记忆,但我们可以利 ...

  2. Linux共享内存(二)

    Linux共享内存编程实例 原文链接:http://blog.csdn.net/pcliuguangtao/article/details/6526119 /*共享内存允许两个或多个进程进程共享同一块 ...

  3. c++ 共享内存_关于Linux共享内存的实验 [二] - 原因

    关于Linux共享内存的实验 [一] 上文采用的"删文件"和"杀进程"的方法主要是为了快速演示实验现象,但这种做法不利于通过调试手段进一步探究其内在的逻辑.为此 ...

  4. 【Linux共享内存】

    Linux共享内存 一.基本概念 二.常用函数 1. shm_open 2. mmap 3. munmap 4. shm_unlink 5. ftruncate 三.使用示例 四.share内存不足解 ...

  5. linux 共享内存操作(shm_open、mmap、编译链接库:-lz -lrt -lm -lc都是什么库)

    文章目录 linux 共享内存操作(shm_open) 一.背景 二.函数使用说明 shm_open ftruncate(改变文件大小) mmap共享内存 三.示例代码 创建内存共享文件并写入数据 打 ...

  6. linux 共享内存 查看和删除

    在使用共享内存的程序异常退出时,由于没有释放掉共享内存,在调试时会出现错误.您可以使用shell命令来查看与释放已经分配的共享内存,下面将详细说明如何进行查看和释放分配的共享内存的方法. 预备知识 L ...

  7. Linux共享内存编程实例

    /*共享内存允许两个或多个进程进程共享同一块内存(这块内存会映射到各个进程自己独立的地址空间)从而使得这些进程可以相互通信.在GNU/Linux中所有的进程都有唯一的虚拟地址空间,而共享内存应用编程接 ...

  8. LINUX共享内存使用常见陷阱与分析(转)

    所谓共享内存就是使得多个进程可以访问同一块内存空间,是最快的可用IPC形式.是针对其他通信机制运行效率较低而设计的.往往与其它通信机制,如信号量结合使用,来达到进程间的同步及互斥.其他进程能把同一段共 ...

  9. linux 共享内存_盘点那些linux 后台开发类常见问题及知识点

    一.linux和os: netstat :显示网络状态 tcpdump:主要是截获通过本机网络接口的数据,用以分析.能够截获当前所有通过本机网卡的数据包.它拥有灵活的过滤机制,可以确保得到想要的数据. ...

  10. linux 共享内存_什么是物理/虚拟/共享内存——Linux内存管理小结一

    物理内存和虚拟内存到底有什么区别? 提到内存,我们会想到经常接触的三个词:虚拟内存.物理内存.共享内存.它们分别对应top输出中的VIRT.RES.SHR三列. 1. 物理内存 系统的物理内存被划分为 ...

最新文章

  1. 关于SQL命令中不等号(!=,)
  2. element 修改表单值后表单验证无效_javascript自学记录:表单脚本1
  3. 什么是java前端绑定事件_java复习前端篇——JavaScript
  4. UML建模--序列图建模技巧
  5. 今天碰到一道比较有趣的面试题,大家来探讨一下。
  6. 2020 我的C++学习之路 C++PrimerPlus第六章课后习题
  7. BZOJ4855 : [Jsoi2016]轻重路径
  8. ERROR 1819 (HY000): Your password does not satisfy the current policy requirements
  9. JAVA基础——编程练习(二)
  10. mongodb最详细的安装与配置
  11. Python笔记-uiautomator2环境搭建(安卓模拟器测试环境+windows开发环境)
  12. 【转】TranslateAnimation详解
  13. python generator
  14. OSError: exception: access violation writing 0x0000000000000000
  15. 计算机论文 大学保研,保研北大,两篇论文,三项专利,这是她的大学
  16. 男生说fb是什么梗_男生聊污是什么意思 男生会对谁聊污
  17. 华为电脑如何投屏到电视linux,华为 P30 如何投屏到电脑
  18. Python 正则提取字符串中的地区
  19. Linux宝塔不显示验证码,树莓派安装宝塔面板后,在登录时无法显示验证码
  20. 【Wi-Fi 802.11协议】管理帧 之 Beacon帧详解

热门文章

  1. Android_项目文件结构目录分析
  2. vector function trmplate
  3. ZooKeeper启动过程2:FastLeaderElection
  4. [慢查优化]联表查询注意谁是驱动表 你搞不清楚谁join谁更好时请放手让mysql自行判定...
  5. 数据结构与算法分析-第一章Java类(02)
  6. python保存为xlsb_Read XLSB File in Pandas Python
  7. mysql5.7.17解压版安装_Windows中 MySQL5.7.17解压版安装步骤
  8. java1a2b3c4d5e6f_用两个线程,一个输出字母,一个输出数字,交替输出1A2B3C4D...26Z...
  9. 判断sem信号量为零_将信号量递减为零的进程崩溃时,如何恢复信号量?
  10. numpy维度交换_“lazy”的transpose()函数——从numpy 数组的内存布局讲起