今天是个好日子,洋人之节乃全球同庆,圣诞一来感觉就要过年了,不过今晚心情有点打折扣,给心爱的人打电话没有打通,本想在平安夜送上快乐的祝福给她,糟糕的心情让自己好像泄了气的皮球一样,无精打彩,心情灰暗,不过我爱的人只要幸福快乐,一个电话又值得了几个钱,也许她也在欢庆,那此时的我也要同庆啦,在这美好的夜晚我该如何度过呢,当然是学习啦,集中去干一件自己喜欢的事当然也无比快乐美好的,稍微抒发了一下内心,言归正传~

1、用管道或者消息队列传递数据

这个示意图的功能是服务器向客户端传输文件,如下:

①、首先要将文件从内核读取到进程的用户空间当中,所以这里就涉及到了一次read()系统调用。

②、服务器需要将读取到的数据拷贝到管道或消息队列当中,涉及到第二次系统调用。

③、对于客户端来说,需要从管道或消息队列中读取这些数据,涉及到第三次系统调用。

④、读到这些数据到应用的数据缓冲区当中,然后将缓冲区的内容写到输出文件中,涉及到第四次系统调查用。

从以上步骤来看,总共涉及到了四次系统调用, 四次内存拷贝(从内核空间到用户空间),那共享内容方式又如何呢?

2、用共享内存传递数据

下面来学习一下相关函数的使用:

下面来看一下内存映射文件示意图:

下面则用代码来实践一下:

下面来创建一个文件:

下面来运行一下:

接下来对文件进行映射:

当映射成功之后,接下来则往文件中写入一些数据,这时候就可以直接通过指针写入了,对文件的操作就好像对内存的访问,如下:

下面来运行一下:

可见就通过内存的方式来对文件进行了数据写入,这就是内存映射文件的作用。

下面来写一个读取文件内容的功能,将写入的五个同学的数据读出来,基于mmap_write.c来写,代码差不多:

mmap_read.c:

#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <sys/mman.h> #include <stdlib.h>
#include <stdio.h>
#include <errno.h>
#include <string.h> #define ERR_EXIT(m) \
do \
{ \
perror(m); \
exit(EXIT_FAILURE); \
} while() typedef struct stu
{
char name[];
int age;
} STU; int main(int argc, char *argv[])
{
if (argc != )
{
fprintf(stderr, "Usage: %s <file>\n", argv[]);
exit(EXIT_FAILURE);
} int fd;
fd = open(argv[], O_RDWR);
if (fd == -)
ERR_EXIT("open"); STU *p;
p = (STU*)mmap(NULL, sizeof(STU)*, PROT_READ | PROT_WRITE, MAP_SHARED, fd, );
if (p == NULL)
ERR_EXIT("mmap"); //从映射内存中,来读取文件的内容
int i;
for (i=; i<; i++)
{
printf("name = %s age = %d\n", (p+i)->name, (p+i)->age);
} munmap(p, sizeof(STU)*);
printf("exit ...\n"); return ;
}

编译运行:

【了解既可】

对共享内存进行写操作的时候:

实际上,这些操作并没有立刻写回到文件当中,内核也会选择一个比较好的时机将这些内容写入到文件当中,如果我们想要立刻写回到文件当中,则就可以用msync函数了。

①、映射不能改变文件的大小

下面来修改一下程序来验证一下:

②、可用于进程间通信的有效地址空间不完全受限于被映射文件的大小

mmap在映射的时候,是将其映射到一个内存页面当中,也就是说,我们可以通讯的区域是以内存页面为单位的,比如我们映射了40个字节,但是内存页面肯定是大于40个字节的,所以能够通信的有效地址空间肯定是超过了40个字节,下面也用程序来说明一下:

编译运行:

在写进程还没结束时,再快速地运行读进程时,从中可以发现读到了10个学生信息,这也就论证了这点,为什么能读到10个学生信息,因为我们所映射的内存共享区大于文件的内容,因为映射的时候是基于页面来分配的,我们映射了40个字节,可能分配了4K的空间,只要我们在这4K的地址空间中访问就不会出错,如果我们超过了4K的地址空间,则很可能会产生一个SIGBUS的信号,如果我们访问的大小超过了几个内存页面,则有可能还会产生一个SIGSEGV信号,这取决于我们超出部份的大小。

而如果写进程结束了,再来读取,从实验结果来看,后面的五个学生信息就读取不到了,为什么呢?因为写进程结束了,也就是先前的那块内存映射区域,对于读端进程来说已经看不到了,这时读端进程又去从文件当中进行映射,只能够看到五个学生的信息了,所以说为啥要用sleep 10来说明这一问题。

③、文件一旦被映射后,所有对映射区域的访问实际上是对内存区域的访问。映射区域内容写回文件时,所写内容不能超过文件的大小,

好了,今天就学到这,有些难理解,可以好好消化,下回见~

linux网络编程之共享内存介绍的更多相关文章

  1. Linux环境编程之共享内存区(一):共享内存区简单介绍

    共享内存区是可用IPC形式中最快的.一旦内存区映射到共享它的进程的地址空间,进程间数据的传递就不再涉及内核.然而往该共享内存区存放信息或从中取走信息的进程间通常须要某种形式的同步.不再涉及内核是指:进 ...

  2. [转] - Linux网络编程 -- 网络知识介绍

    (一)Linux网络编程--网络知识介绍 Linux网络编程--网络知识介绍客户端和服务端         网络程序和普通的程序有一个最大的区别是网络程序是由两个部分组成的--客户端和服务器端. 客户 ...

  3. Linux网络编程入门 (转载)

    (一)Linux网络编程--网络知识介绍 Linux网络编程--网络知识介绍客户端和服务端         网络程序和普通的程序有一个最大的区别是网络程序是由两个部分组成的--客户端和服务器端. 客户 ...

  4. 【转】Linux网络编程入门

    (一)Linux网络编程--网络知识介绍 Linux网络编程--网络知识介绍客户端和服务端         网络程序和普通的程序有一个最大的区别是网络程序是由两个部分组成的--客户端和服务器端. 客户 ...

  5. 《转》Linux网络编程入门

    原地址:http://www.cnblogs.com/duzouzhe/archive/2009/06/19/1506699.html (一)Linux网络编程--网络知识介绍 Linux网络编程-- ...

  6. Linux网络编程--进程间通信(一)

    进程间通信简介(摘自<Linux网络编程>p85) AT&T 在 UNIX System V 中引入了几种新的进程通讯方式,即消息队列( MessageQueues),信号量( s ...

  7. Linux网络编程入门

    (一)Linux网络编程--网络知识介绍 Linux网络编程--网络知识介绍客户端和服务端         网络程序和普通的程序有一个最大的区别是网络程序是由两个部分组成的--客户端和服务器端. 客户 ...

  8. Linux网络编程&内核学习

    c语言: 基础篇 1.<写给大家看的C语言书(第2版)> 原书名: Absolute Beginner's Guide to C (2nd Edition) 原出版社: Sams 作者: ...

  9. 服务器编程入门(4)Linux网络编程基础API

      问题聚焦:     这节介绍的不仅是网络编程的几个API     更重要的是,探讨了Linux网络编程基础API与内核中TCP/IP协议族之间的关系.     这节主要介绍三个方面的内容:套接字( ...

随机推荐

  1. web端自动化——selenium3+Python3+pycharm自动化

    1.前言: 对于初学者来说,python自带的IDLE,精简又方便,不过一个好的编辑器能让python编码变得更方便,更加优美些. 不过呢,也可以自己去下载其他更好用的代码编辑器,在这推荐: PyCh ...

  2. Python3-ibm_db模块-数据库操作之DB2

    官方文档 https://www.ibm.com/support/knowledgecenter/SSEPGG_9.5.0/kc_gen/developing-gen1.html 模块安装 Windo ...

  3. 如何提高程序员的键盘使用效率(搬砖工人的自我修养(tucao))

    高软第一次作业 程序员使用键盘最常用的技能 搬运自:https://learnku.com/articles/22806    括号内为个人吐槽 1.尊重操作系统特性(如Mac OS的某些键位自定义设 ...

  4. C++ 枚举定义

    我们在平常的编程中,时常需要为一些属性定义一组可以选择的值,比如文件打开的状态可能会有三种:输入 输出和追加 我们一般情况下记录这些状态是让每一个状态和一个常数相对应   比如 ; ; ; 这个方法虽 ...

  5. Echart timeline 高级用法!!!!

    一.前言 在使用 echart timeline 来着图形可视化时,我使用的和官网也不一样,因为我有使用映射关系.比如我将 no 映射到X轴,将 d4 映射到Y轴. 二.参考 echart官网:htt ...

  6. C++基础(静态数据成员和静态成员函数)

    [简介] 1.静态数据成员在类中声明,在源文件中定义并初始化: 2.静态成员函数没有this指针,只能访问静态数据成员: 3.调用静态成员函数:(1)对象.(2)直接调用: 4.静态成员函数的地址可用 ...

  7. zblog安装环境介绍?zblog安装需要什么环境

    最近在群里看到很的多人有在问:“安装zblog需要什么环境?”,其实这个问题在zblog官网的程序下载页面有说明,但是不太详细,那么本文的目的就是来给大家介绍下zblog安装环境详细说明. zblog ...

  8. 【LEETCODE】33、LeetCode的Given a non-negative integer numRows, generate the first numRows of Pascal's triangle

    package y2019.Algorithm.array; import java.util.ArrayList; import java.util.List; /** * @ProjectName ...

  9. Vue、SPA实现登陆

    axios/qs/vue-axios安装及使用步骤 首先我们要下载三个依赖包,方便后面的开发使用需要: npm install axios -S   axios是vue2提倡使用的轻量版的ajax.它 ...

  10. spring整合MQ

    ---恢复内容开始--- 一. 导入依赖 <dependencies> <!-- ActiveMQ客户端完整jar包依赖 --> <dependency> < ...