基于linux下的高并发服务器开发(第二章)- 2.17 内存映射(1)

news2024/12/23 5:50:21

 11 / 内存映射相关系统调用 

#include <sys/mman.h>

void* mmap(void *addr, size_t length, int prot, int flags,int fd, off_t offset);

    - 功能:将一个文件或者设备的数据映射到内存中

    - 参数:

        - void* addr:NULL,由内核指定

        - length:要映射的数据的长度,这个值不能为0。建议使用文件的长度

                获取文件的长度: stat lseek

        - prot:对申请的内存映射区的操作权限

            - PROT_EXEC : 可执行的权限

            - PROT_READ : 读权限

            - PROT_WRITE : 写权限

            - PROT_NONE : 没有权限

            要操作映射内存,必须要有读的权限

            PROT_READ、PROT_READ|PROT_WRITE

        - flags:

            - MAP_SHARED : 映射区的数据会自动和磁盘文件进行同步,进程间通信,必须要设置这个选项

            - MAP_PRIVATE : 不同步,内存映射区的数据改变了,对原来的文件不会修改,会重新创建一个新的文件。(copy on write)

        - fd:需要映射的那个文件的文件描述符

            - 通过open得到,open的是一个磁盘文件

            - 注意文件的大小不能为0,open指定的权限不能和prot参数有冲突

                prot:PROT_READ                 open:只读/读写

                prot:PROT_READ | PROT_WRITE    open:读写

         - offset:偏移量,一般不用。必须指定的是4k的整数倍,0表示不偏移

    - 返回值:返回创建的内存的首地址

        失败返回MAP_FAILED,(void*) -1

int munmap(void *addr, size_t length);

    - 功能:释放内存映射

    - 参数:

        - addr:要释放内存的首地址

        - length:要释放的内存的大小,要和mmap函数中的length参数的值一样

使用内存映射实现进程间的通信:

1、有关系的进程(父子进程)

    - 还没有子进程的时候

        - 通过唯一的父进程,先创建内存映射区

    - 有了内存映射区以后,创建子进程

    - 父子进程共享创建的内存映射区

2、没有关系的进程间通信

    - 准备一个大小不是0的磁盘文件

    - 进程1 通过磁盘文件创建内存映射区

        - 得到一个操作这块内存的指针

    - 进程2 得到磁盘文件创建内存映射区

        - 得到一个操作这块内存的指针

    - 使用内存映射区通信

注意:内存映射区通信,是非阻塞

1、有关系的进程(父子进程) 

/*
    #include <sys/mman.h>
    void* mmap(void *addr, size_t length, int prot, int flags,int fd, off_t offset);
        - 功能:将一个文件或者设备的数据映射到内存中
        - 参数:
            - void* addr:NULL,由内核指定
            - length:要映射的数据的长度,这个值不能为0。建议使用文件的长度
                    获取文件的长度: stat lseek
            - prot:对申请的内存映射区的操作权限
                - PROT_EXEC : 可执行的权限
                - PROT_READ : 读权限
                - PROT_WRITE : 写权限
                - PROT_NONE : 没有权限
                要操作映射内存,必须要有读的权限
                PROT_READ、PROT_READ|PROT_WRITE
            - flags:
                - MAP_SHARED : 映射区的数据会自动和磁盘文件进行同步,进程间通信,必须要设置这个选项
                - MAP_PRIVATE : 不同步,内存映射区的数据改变了,对原来的文件不会修改,会重新创建一个新的文件。(copy on write)
            - fd:需要映射的那个文件的文件描述符
                - 通过open得到,open的是一个磁盘文件
                - 注意文件的大小不能为0,open指定的权限不能和prot参数有冲突
                    prot:PROT_READ                 open:只读/读写
                    prot:PROT_READ | PROT_WRITE    open:读写

                - offset:偏移量,一般不用。必须指定的是4k的整数倍,0表示不偏移
        - 返回值:返回创建的内存的首地址
            失败返回MAP_FAILED,(void*) -1
    
    int munmap(void *addr, size_t length);
        - 功能:释放内存映射
        - 参数:
            - addr:要释放内存的首地址
            - length:要释放的内存的大小,要和mmap函数中的length参数的值一样
*/

/*
    使用内存映射实现进程间的通信:
    1、有关系的进程(父子进程)
        - 还没有子进程的时候
            - 通过唯一的父进程,先创建内存映射区
        - 有了内存映射区以后,创建子进程
        - 父子进程共享创建的内存映射区

    2、没有关系的进程间通信
        - 准备一个大小不是0的磁盘文件
        - 进程1 通过磁盘文件创建内存映射区
            - 得到一个操作这块内存的指针
        - 进程2 得到磁盘文件创建内存映射区
            - 得到一个操作这块内存的指针
        - 使用内存映射区通信
    注意:内存映射区通信,是非阻塞
*/
#include <stdio.h>
#include <sys/mman.h>
#include <fcntl.h>
#include <sys/types.h>
#include <unistd.h>
#include <stdlib.h>
#include <wait.h>
#include <string.h>

// 留个作业:使用内存映射实现没有关系的进程间的通信
int main(){

    // 1、打开一个文件
    int fd = open("test.txt",O_RDWR);
    int size = lseek(fd,0,SEEK_END); //获取文件的大小

    //2、创建内存映射区
    void* ptr = mmap(NULL,size,PROT_READ | PROT_WRITE,MAP_SHARED,fd,0);
    if(ptr == MAP_FAILED){
        perror("mmap");
        exit(0);
    }

    //3、创建子进程
    pid_t pid = fork();
    if(pid > 0){
        wait(NULL);
        //父进程
        char buf[64];
        strcpy(buf,(char*)ptr);
        printf("read data : %s\n",buf);
    }else if(pid == 0){
        //子进程
        strcpy((char*)ptr,"nihao a,son!!!");
    }

    // 关闭内存映射区
    munmap(ptr,size);
     
    return 0;
}

2、没有关系的进程间通信

mmap-ipc-write.c

//mmap-ipc-write.c
/*
    没有关系的进程间通信
    - 准备一个大小不是0的磁盘文件
    - 进程1 通过磁盘文件创建内存映射区,得到一个操作这块内存的指针
    - 进程2 通过磁盘文件创建内存映射区,得到一个操作这块内存的指针
    - 使用内存映射区通信
*/
// 这个文件负责把test.txt映射,并往里面写入
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h> //open函数头文件
#include <unistd.h>//lseek函数头文件
#include <sys/mman.h> //mmap
#include <string.h>//strcpy
#include <stdlib.h>//exit
#include <stdio.h>//perror

int main(){
    // 1、打开一个文件
    int fd = open("test.txt",O_RDWR);
    int size = lseek(fd,0,SEEK_END);//获取文件的大小

    //2、创建内存映射区
    void* ptr = mmap(NULL,size,PROT_READ | PROT_WRITE,MAP_SHARED,fd,0);
    if(ptr == MAP_FAILED){
        perror("mmap");
        exit(0);
    }

    strcpy((char*)ptr,"heheda");
    
    // 关闭内存映射区
    munmap(ptr, size);

    return 0;
}

mmap-ipc-read.c

//mmap-ipc-read.c
/*
    没有关系的进程间通信
    - 准备一个大小不是0的磁盘文件
    - 进程1 通过磁盘文件创建内存映射区,得到一个操作这块内存的指针
    - 进程2 通过磁盘文件创建内存映射区,得到一个操作这块内存的指针
    - 使用内存映射区通信
*/
// 这个文件负责把test.txt映射,并从里面读取,然后关闭内存映射区
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>//open函数头文件
#include <unistd.h>//lseek函数头文件
#include <sys/mman.h>//mmap
#include <string.h>//strcpy
#include <stdlib.h>//exit
#include <stdio.h>//perror

int main(){
    // 1、打开一个文件
    int fd = open("test.txt",O_RDWR);
    int size = lseek(fd,0,SEEK_END);//获取文件的大小

    //2、创建内存映射区
    void* ptr = mmap(NULL,size,PROT_READ | PROT_WRITE,MAP_SHARED,fd,0);
    if(ptr == MAP_FAILED){
        perror("mmap");
        exit(0);
    }

    char buf[64];
    strcpy(buf,(char*)ptr);
    printf("read data : %s\n",buf);
    
    // 关闭内存映射区
    munmap(ptr, size);
    return 0;
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/777743.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

【OpenCV】常见问题及解决办法

文章目录 0 前言1 中文乱码问题2 非法路径问题 0 前言 本篇博客主要是总结OpenCV使用过程中遇到的一些问题&#xff0c;以及对应的解决办法&#xff0c;这里重点是关注OpenCV&#xff0c;既有基于C的&#xff0c;也有基于Python的&#xff0c;比较全面&#xff0c;而且也会随着…

【Python】数据分析+数据挖掘——变量列的相关操作

前言 在Python和Pandas中&#xff0c;变量列操作指的是对DataFrame中的列进行操作&#xff0c;包括但不限于选择列、重命名列、添加新列、删除列、修改列数据等操作。这些操作可以帮助我们处理数据、分析数据和进行特征工程等。 变量列的相关操作 概述 下面将会列出一些基本…

对github项目提PR 请求的保姆级教程——以修改casdoor项目的swagger文档为例,干货满满

Github入门教程可以在腾讯犀牛鸟开源人才培养计划里面学习。 PR简介 PR(Pull Request) 即拉取请求,是 GitHub 上进行协同开发的一种非常常用的方式。 它的基本流程是&#xff1a; 开发者fork一个开源项目的代码库,将其克隆到本地。在本地对代码进行修改、添加新功能等。将本…

基于ArcGIS、ENVI、InVEST、FRAGSTATS等多技术融合提升环境、生态、水文、土地、土壤、农业、大气等领域的数据分析能力与项目科研水平教程

详情点击链接&#xff1a;基于ArcGIS、ENVI、InVEST、FRAGSTATS等多技术融合提升环境、生态、水文、土地、土壤、农业、大气等领域的数据分析能力与项目科研水平 一&#xff0c;空间数据获取与制图 1.1 软件安装与应用 1.2 空间数据 1.3海量空间数据下载 1.4 ArcGIS软件快…

MySQL数据库(七)

目录 一、联合查询 1.1内连接 1.2外连接 1.3自连接 1.4子查询 1.5合并查询 一、联合查询 实际开发中往往数据来自不同的表&#xff0c;所以需要多表联合查询。多表查询是对多张表的数据取笛卡尔积&#xff1a; 下面进行多表查询的练习&#xff0c;对应的在表的设计与数据插入中…

练习时长两年半的网络安全防御“first”

1.网络安全常识及术语 下边基于这次攻击演示我们介绍一下网络安全的一些常识和术语。 资产 任何对组织业务具有价值的信息资产&#xff0c;包括计算机硬件、通信设施、 IT 环境、数据库、软件、文档资料、信息服务和人员等。 网络安全 网络安全是指网络系统的硬件、软件及…

Stable Diffusion - 扩展 Roop 换脸 (Face Swapping) 插件的配置与使用

欢迎关注我的CSDN&#xff1a;https://spike.blog.csdn.net/ 本文地址&#xff1a;https://spike.blog.csdn.net/article/details/131856141 官网&#xff1a;GitHub - roop&#xff0c;参考论文&#xff1a;RobustSwap: A Simple yet Robust Face Swapping Model against Attr…

kubesphere部署谷粒商城, nginx无法路由到网关服务

使用kubesphere部署谷粒商城&#xff0c;微服务和nginx均已部署成功&#xff0c;其中ingress-controller已安装。但是nginx无法路由到网关服务。使用域名gulimall.com访问谷粒商城&#xff0c;默认访问的是nginx首页&#xff0c;路由失败。 校对nginx的配置信息&#xff0c;上游…

MySQL数据库第十课-------join连接的再续------强强连锁

作者前言 欢迎小可爱们前来借鉴我的gtiee秦老大大 (qin-laoda) - Gitee.com __________________________________________________________ 目录 join连接 内连接 左连接 右连接 外连接 其他连接 ______________________________________________________________ 作…

Unity 实用插件篇 | Tutorial Master 2 游戏引导教程 快速上手

前言【Unity 实用插件篇】 | Tutorial Master 2 游戏引导教程 快速上手一、Tutorial Master 2 介绍1.1 基本概念1.2 相关链接1.3 效果展示二、搭建简易测试环境三、制作简易引导教程3.1 挂载一个Tutorial Master Manager脚本3.2 设置引导预制体3.3 创建一个引导教程3.4 添加引导…

SpringBoot系列--【如何集成prometheus?】

如何集成prometheus&#xff1f; 1.添加pom依赖 注意&#xff1a;prometheus的版本依赖springboot版本&#xff0c;示例使用的springboot版本的2.3.X. 2.配置文件添加配置 3.主启动类添加如下配置 4.验证端点 SpringBoot项目到这里就配置完成了&#xff0c;启动项目&#xff0c…

将请求参数数据推送至RabbitMQ队列中并且捕捉消息没有到达交换机的异常

1&#xff1a;自定义mq信息类&#xff08;我的交换这些信息都从nacos上直接取的&#xff0c;怎么从nacos取配置信息看上篇文章&#xff09;&#xff1a; import lombok.AllArgsConstructor; import lombok.Builder; import lombok.Data; import lombok.NoArgsConstructor;impo…

Windows10 + Mingw + Paho Mqtt C/C++编译使用

文章目录 1、前言2、按照Mingw环境3、编译paho c3.1、ssl验证大坑3.2、解决方法3.3、mingw32-make过程出现报错3.4、继续出错3.5、编译成功 4、编译paho c5、Qt使用paho mqtt库5.1、编码 1、前言 起初使用的是Cmake Visual Studio 2019进行编译&#xff0c;使用的时候出现ssl错…

《Java核心技术大会2023》——AIC松鼠活动第一期

共同深入探讨 Java 生态&#xff01;直播预约&#xff1a;视频号“IT阅读排行榜” 大会简介 人工智能在22年、23年的再次爆发让Python成为编程语言里最大的赢家&#xff1b;云原生的持续普及令Go、Rust等新生的语言有了进一步叫板传统技术体系的资本与底气。我们必须承认在近…

【搜索引擎Solr】配置 Solr 以获得最佳性能

Apache Solr 是广泛使用的搜索引擎。有几个著名的平台使用 Solr&#xff1b;Netflix 和 Instagram 是其中的一些名称。我们在 tajawal 的应用程序中一直使用 Solr 和 ElasticSearch。在这篇文章中&#xff0c;我将为您提供一些关于如何编写优化的 Schema 文件的技巧。我们不会讨…

基于linux下的高并发服务器开发(第二章)- 2.14 管道的读写特点和管道设置为非阻塞

管道的读写特点&#xff1a; 使用管道时&#xff0c;需要注意以下几种特殊的情况&#xff08;假设都是阻塞I/O操作&#xff09; 1.所有的指向管道写端的文件描述符都关闭了&#xff08;管道写端引用计数为0&#xff09;&#xff0c;有进程从管道的读端读数据&#xff0c;那么管…

SpringBoot系列--【K8s中的SpringBoot如何给应用配置健康检查?】

K8s中的SpringBoot如何给应用配置健康检查&#xff1f; 1.健康检查的必要性 作为业务监控的首要目标&#xff0c;服务的存活性&#xff0c;也就是它的健康状况&#xff0c;成为了重中之重&#xff0c;容器云平台可以根据健康检查策略来对服务实例进行自动重启或从负载均衡中摘除…

IP-GUARD如何在客户端上进行审批管理?

如何在客户端上进行审批管理&#xff1f; 4 实现步骤如下&#xff1a; 1、先在控制台-加密-加密授权设置-常规中&#xff0c;勾选允许登录审批管理平台开启客户端登录审批管理平台的功能。 2、然后客户端电脑&#xff0c;右键加密托盘登录审批账号后即可正常审批。 如何实现特…

MySQL 8.1.0正式发布!

早在五年前&#xff0c;MySQL 8.0 就发布了第一个 GA 版本&#xff0c;此后一直在这个版本进行更新&#xff0c;而没有升级大版本。最近 MySQL 官方终于发布了 MySQL 8.1.0 和 MySQL 8.0.34&#xff0c;分别代表了创新版和长期支持版。 新版本中与 SQL 相关的改进包括保存执行计…

用C++在Windows桌面上打个叉❌

我们的目标是&#xff0c;只写一二十行代码&#xff0c;用 Windows自带的原生接口&#xff0c;强行在桌面上打个大红❌&#xff0c;如图&#xff1a; 写了大半年C&#xff0c;天天和“黑乎乎” 的小窗口你侬我侬&#xff1f;赶紧来打开一扇“Windows”&#xff0c;从窗口跳进全…