147|0

7202

帖子

192

TA的资源

五彩晶圆(高级)

楼主
 

《Linux内核深度解析》第三章 内存学习笔记1 [复制链接]

内存学习之内存映射学习笔记

 

内存管理架构可以分为:用户空间、内核空间及硬件部分3个层面:

用户空间:应用程序使用malloc()申请内存资源/free()释放内存资源。

内核空间:内核总是驻留在内存中,是操作系统的一部分。内核空间为内核保留,不允许应用程序读写该区域的内容或直接调用内核代码定义的函数。

硬件:处理器包含一个内存管理单元Memory Management Uint,MMU的部件,负责把虚拟地址转换为物理地址。内存管理单元包含一个页表缓存的部件,保存最近使用过的页表映射,避免每次把虚拟地址转换成物理地址都需要查询内存中的页表。

Linux内核的核心功能:

 

不管是用户空间还是内核空间,使用的地址都是虚拟地址,当需进程要实际访问内存的时候,会由内核的「请求分页机制」产生「缺页异常」调入物理内存页

 

程序只能通过虚拟地址访问外设寄存器,内核提供了一下函数来把外设寄存器的物理地址映射到虚拟地址空间

(1)ioremap()把外设寄存器的物理地址映射到内核虚拟地址空间

(2)io_remap_pfn_range()把外设寄存器的物理地址映射到进程的用户虚拟地址空间

 

内存映射是在进程的虚拟地址空间中创建一个映射,分为2种

  1. 文件映射:文件支持的内存映射,把文件的一个区间映射到进程的虚拟地址空间,数据源是存储设备上的文件
  2. 匿名映射:没有文件支持的内存映射,把物理内存映射到进程的虚拟地址空间,没有数据源

也可以说内存映射就是磁盘文件的数据映射到内存,用户可以通过修改内存就能修改磁盘文件。简单来说就是将同一个文件存储映射到不同的进程中,两个进程通过改变文件内容(读写内存)来实现通信,不必在使用read和write函数等系统调用,加快文件的读取和写入。

 

 

 

 

原型: void *mmap(void *addr, size_t length, int prot, int flags, int fd, off_t offsize);

返回值: 成功则返回映射区起始地址, 失败则返回MAP_FAILED(-1).

参数:

 

1.addr: 指定映射的起始地址, 通常设为NULL, 由系统指定.

2.length: 将文件的多大长度映射到内存.

3.prot: 映射区的保护方式, 可以是:

PROT_EXEC: 映射区可被执行.

PROT_READ: 映射区可被读取.

PROT_WRITE: 映射区可被写入.

PROT_NONE: 映射区不能存取.

4.flags: 映射区的特性, 可以是:

MAP_SHARED: 对映射区域的写入数据会复制回文件, 且允许其他映射该文件的进程共享.

MAP_PRIVATE: 对映射区域的写入操作会产生一个映射的复制(copy-on-write), 对此区域所做的修改不会写回原文件.

fd: 由open返回的文件描述符, 代表要映射的文件.

offset: 以文件开始处的偏移量, 必须是分页大小的整数倍, 通常为0, 表示从文件头开始映射.

 

测试例程

#include<string.h>

#include<stdio.h>

#include<stdlib.h>

#include<sys/types.h>

#include<sys/stat.h>

#include<unistd.h>

#include<fcntl.h>

#include<sys/mman.h>



int main(int argc, const char* argv[]) {

    int fd = -1;

    int ret = -1;

    void* addr = NULL;



    // 1.以读写的方式打开txt文件

    fd = open("txt", O_RDWR);

    if (-1 == fd) {

        perror("open");

        return 1;

    }

    // 2.将文件映射到进程的虚拟地址空间

    addr = mmap(NULL, 1024, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);

    if (addr == MAP_FAILED) {

        perror("mmap");

        return 1;

    }



    printf("映射成功.\n");

    // 3.关闭文件

    close(fd);

    // 4.写文件

    memcpy(addr, "123456", 6);

    // 5.断开存储映射

    munmap(addr, 1024);



    return 0;

}

执行结果

 

 

点赞 关注

回复
举报
您需要登录后才可以回帖 登录 | 注册

随便看看
查找数据手册?

EEWorld Datasheet 技术支持

相关文章 更多>>
关闭
站长推荐上一条 1/8 下一条

 
EEWorld订阅号

 
EEWorld服务号

 
汽车开发圈

About Us 关于我们 客户服务 联系方式 器件索引 网站地图 最新更新 手机版

站点相关: 国产芯 安防电子 汽车电子 手机便携 工业控制 家用电子 医疗电子 测试测量 网络通信 物联网

北京市海淀区中关村大街18号B座15层1530室 电话:(010)82350740 邮编:100190

电子工程世界版权所有 京B2-20211791 京ICP备10001474号-1 电信业务审批[2006]字第258号函 京公网安备 11010802033920号 Copyright © 2005-2025 EEWORLD.com.cn, Inc. All rights reserved
快速回复 返回顶部 返回列表