30分钟搞懂Linux内核内存映射,值得大神们收藏
gudong366 2025-03-09 16:54 14 浏览
一、内存映射基础知识
1、内核地址映射模型
比如:X86CPU采用段页式地址映射模型,进程代码地址为逻辑地址,经过段页式地址映射之后,才能够真正访问物理内存。32位Linux内核地址空间划分:0GB--3GB为用户空间,3GB--4GB为内核空间。32位和64位内核地址空间划分是不同的。具体空间表示如下:
2、内核高端内存
比如:当内核模块代码或络访问内存时,代码中的地址为逻辑地址,而且对应到真正的物理内存地址,需要地址和它一对一的映射,假设:逻辑地址0xc0000003对应的物理地址为0x3。内核逻辑地址空间访问为0xc0000000--0xFFFFFFFF,那么对应的物理内存范围为0x0--0x40000000。即只能访问1GB物理内存。假设我们的电脑8GB物理内存,那么内核就只能访问前面1GB物理内存,剩下7GB物理内存它无法访问,因为内核的地址空间已经全部映射到物理内存地址范围0x--0x40000000。
Linux将内核地址空间划分为三部分:
ZONE_DMA/ZONE_NORMAL/ZONE_HIGHMEM。高端内存HIGH_MEM地址空间范围为0xF8000000--0xFFFFFFFF(896MB-1024MB)。针对高端内存的最基本思想:借一段地址空间,建立临时地址映射,用完后释放,达到此段地址空间可以循环使用,访问所有物理内存。
3、内存映射
内存映射是在进程的虚拟地址空间中创建一个映射,可分为两种:
A、文件映射(文件支持的内存映射,把文件的一个区间映射到进程的虚拟地址空间,数据源是存储设备上文件);
B、匿名映射(没有文件支持的内存映射,把物理内存映射到进程的虚拟地址空间,没有数据源)。通常把文件映射的物理页称为文件页,把匿名映射的物理页称为匿名页。
4、根据修改是否对其他进程可见和是否传递到底层文件,内存映射分为共享映射和私有映射。
A、共享映射:修改数据时映射相同区域的其他进程可以看见,如果是文件支持的映射,修改会传递到底层文件。
B、私有映射:第一次修改数据时会从数据源复制一个副本,然后修改副本,其他进程看不见,不影响我们的数据源。
两个进程可以使用共享的文件映射实现共享内存。匿名映射通常为私有映射,共享的匿名映射只可能出现在父进程和子进程之间。在进程的虚拟地址空间中,代码段和数据段是私有的文件映射,未初始化数据段、堆栈是私有的匿名映射。
5、内存映射原理机制:
1、创建内存映射的时,在进程的用户虚拟地址空间中分配一个虚拟内存区域(vm_area_struct);
2、Linux内核采用延迟分配物理内存的策略,在进程第一次访问虚拟页的时候,产生缺页异常,如果是文件映射,那么分配物理页,把文件指定区间的数据读到物理页中,然后在页表中把虚拟页映射到物理页;如果你是匿名映射,那么分配物理页,然后在页表中把虚拟页映射到物理页。
二、应用层API系统调用
Linux内核当中内存管理子系统提供给我们用户层的系统调用API函数,具体如下:
头文件:#include 1、用来创建内存映射
void *mmap(void *addr, size_t length, int prot, int flags,int fd, off_t offset);
2、用来删除内存映射
int munmap(void *addr, size_t length);
3、专用用来扩大或缩小已经存在的内存映射,可能同时移动
#define _GNU_SOURCE /* See feature_test_macros(7) */ #include void *mremap(void *old_address, size_t old_size, size_t new_size, int flags, ... /* void *new_address */);
4、用来设置堆的上界
#include
int brk(void *addr);
5、用来创建非线性的文件映射,即文件区域和虚拟地址空间之间的映射不是线性关系,现在已不用
#define _GNU_SOURCE /* See feature_test_macros(7) */ #include
int remap_file_pages(void *addr, size_t size, int prot, size_t pgoff, int flags);
6、用来设置虚拟内存区域的访问权限
#include
int mprotect(void *addr, size_t len, int prot);
在Linux空间中可以使用如下函数:
1、把内存的物理页映射到进程的虚拟地址空间,这个函数用处是:实现进程和内核共享内存。
int remap_pfn_range (struct vm_area_struct *vma,unsigned long addr,unsigned long pfn,unsigned long size,pgprot_t prot);
2、把外设寄存器的物理地址映射到进程的虚拟地址空间,进程可能直接访问外设寄存器。
int io_remap_page_range(struct vm_area_struct *vma, unsigned long virt_addr,unsigned long phys_addr, unsigned long size,pgprot_t prot);
应用层当中应用程序通过使用C标准库提供的函数malloc()申请内存。glibc库的内存分配器ptmalloc使用brk或mmap向内核以页为单位申请虚拟内存,然后把页划分成小内存块分配给应用程序。默认的阈值为128KB,如果应用程序申请的内存长度小于阈值,ptmalloc分配器使用brk向内核申请虚拟内存,否则ptmalloc分配器使用mmap内内核申请虚拟内存。应用程序可以直接使用mmap向内核申请虚拟内存。
三、Linux内核常用数据结构
1、进程描述符
2、内存描述符
3、虚拟内存区域
4、mmap系统调用
a.进程创建匿名的内存映射,把内存的物理页映射到进程的虚拟地址空间;
b.进程把文件映射到进程的虚拟地址空间,可以像访问内存一样访问文件,不需要调用系统调用read()/write()访问文件,从面避免用户模式和内核模式之间的切换,提高读写文件的速度。
c.两个进程针对同一个文件创建共享的内存映射,实现共享会败在。
函数原型:
#include void *mmap(void *addr, size_t length, int prot, int flags,int fd, off_t offset);
参数如下:
addr:起始虚拟地址,如果addr为0,内核选择虚拟地址。如果addr为非0,内核把这个参数作为提示,在附近选择虚拟地址。
length:映射的长度,单位是字节。
prot:保护位,具体参数如下:
PROT_EXEC:页可执行 PROT_READ:页可读 PROT_WRITE:页可写 PROT_NONE:面不可访问
flags:标志,具体参数如下:
MAP_SHARED:共享映射
MAP_PRIVATE:私有映射
MAP_ANONYMOUS:匿名映射
MAP_FIXED:固定映射
MAP_HUGETLB:使用巨型页
MAP_LOCKED:把页锁在内存中
fd:文件描述符
offset:偏移,单位是字节,必须是页长度的整数倍。
返回值:
返回起始虚拟地址,否则返回负的错误号。
四、创建/删除内存映射
1、创建内存映射
C标准库封装函数mmap()用来创建内存映射,内核提花POSIX标准定义的系统调用mmap,内核系统调用sys_mmap(),具体操作流程如下:
函数sys_mmap_pgoff执行流程视图如下:
a.如果是创建文件映射,根据文件描述符在进程的打开文件表中找到file实例;
b.如果是创建匿名巨型页映射,在hugetlbfs文件系统中创建文件“anon_hugepage",并且创建此文件 的一个打开实例file;
c.调用vm_mmap_pgoff进行处理。
相关推荐
- linux sed系列 第四篇:sed工业实战——日志处理与数据清洗
-
“掌握了sed的编程能力后,我们如同装备精良的工匠,终于可以踏入真实的工业战场。本篇将聚焦sed在日志分析、数据合规化、多文件批处理等场景中的应用,看它如何在海量数据中游刃有余,展现文本处理的...
- Linux下sed的简单使用(linux中sed是什么意思)
-
1、sed简介stremeditor流编辑器,它是一项Linux指令,功能同awk类似,差别在于,sed简单,对列处理的功能要差一些,awk的功能复杂,对列处理的功能比较强大,sed编辑器是一行一...
- linux基础命令之date命令(linux中的date)
-
date命令主要用于显示或者设置系统时间语法格式:date参数对象使用date命令时,最好先使用date--help命令查看支持哪些参数,有些小型Linux系统下的date命令,只支持一些基本参...
- Ubuntu linux 常用命令(ubuntu常用的50个命令)
-
使用dpkg命令来安装.deb包。sudodpkg-i~/example.deb如果在安装过程中遇到依赖问题,可以使用以下命令来修复:sudoapt-getinstall-f将flut...
- Linux基础命令-sed命令(linux教程:sed命令的用法)
-
Sed全名streameditor流编辑器,它是一个强大的文本处理工具,它可以从文件中接受输入,也可以接受来自标准输入流的输入,它擅长取行。Sed的用途非常广泛,包括:1)文本替换2)选择性的输...
- linux sed系列 第二篇:sed进阶技巧——地址定位与正则表达式
-
“上一篇我们掌握了sed的基础替换,如同获得了第一把钥匙。现在,让我们更进一步,学习如何精准锁定目标行,如同拥有了导航地图,让每一次操作都直击要害!”地址定位的四种维度sed的强大,很大程度上源...
- 火狐Firefox浏览器140发布:手动Unload标签页、优化翻译体验等
-
IT之家6月24日消息,Mozilla在发布版本139不到一个月后,推出了最新的开源网页浏览器Firefox140。新版本增加了手动Unload标签页的功能,优化了垂直标签页的调...
- Linux 基本正则表达式及扩展正则表达式功能举例
-
在Linux中,正则表达式(RegularExpression)是一种强大的模式匹配工具,用于在文本中查找、匹配和处理特定模式的字符串。Linux支持两种类型的正则表达式:基本正则表达式(Basic...
- linux下find命令的经典26个使用示例
-
简介find命令是基于unix的操作系统中常用的工具之一。顾名思义,它在目录层次结构中查找文件和目录。用户可以传递不同的参数,并根据文件的名称、扩展名、类型、大小、权限、修改时间、所有者、组等搜索文件...
- linux运维中特殊符号的应用与实践
-
路径位置类的特殊符号(1)、波浪线(~)在linux系统的命令行中,~表示用户的家目录,超级用户为/root,普通用户为/home。假设我当前目录在usr/local下[root@xrylocal]...
- 开源框架log4cpp实战(开源gui框架)
-
1.Log4cpp使用Log4cpp中主要包含Category(种类),Appender(附加器),Layout(布局),Priorty(优先级),NDC(嵌套的诊断上下文)。Category、App...
- Linux find命令详解(linux find -l)
-
一、命令介绍Linuxfind命令是类unix操作系统中最重要和最常用的命令行实用程序之一。find命令用于根据指定的条件搜索和定位与参数匹配的文件和目录列表。find命令提供了广泛的选项,允许用户...
- Linux运维:单引号与双引号的使用(linux 单引号和双引号)
-
1、单引号的使用单引号可以将它中间的所有任意字符还原为字面意义,实现屏蔽Shell元字符的功能。注意不可以在两个单引号中间单独插入一个单引号,单引号必须成对出现。示例1:定义一个变量,并输出变量的...
- Linux技巧:find 命令用法详细说明,看完会有收获
-
在Linux命令中,find是比较复杂难用的命令。使用该命令搜索文件时,常常发现自己找了一些例子能用,但稍微改一下条件,就搜不到想要的结果。下面会以一些实例来说明使用find命令的关键要点和...
- Linux Shell中单引号、双引号、反引号的解释
-
1、单引号('')单引号所见即所得,直接显示单引号里的内容。即单引号里的任何字符都会原样输出,单引号字符串中的变量是无效的。比如下面的例子,单引号所见即所得。2、双引号("...
- 一周热门
- 最近发表
-
- linux sed系列 第四篇:sed工业实战——日志处理与数据清洗
- Linux下sed的简单使用(linux中sed是什么意思)
- linux基础命令之date命令(linux中的date)
- Ubuntu linux 常用命令(ubuntu常用的50个命令)
- Linux基础命令-sed命令(linux教程:sed命令的用法)
- linux sed系列 第二篇:sed进阶技巧——地址定位与正则表达式
- 火狐Firefox浏览器140发布:手动Unload标签页、优化翻译体验等
- Linux 基本正则表达式及扩展正则表达式功能举例
- linux下find命令的经典26个使用示例
- linux运维中特殊符号的应用与实践
- 标签列表
-
- linux一键安装 (31)
- linux运行java (33)
- ln linux (27)
- linux 磁盘管理 (31)
- linux 内核升级 (30)
- linux 运行python (28)
- linux 备份文件 (30)
- linux 网络测试 (30)
- linux 网关配置 (31)
- linux jre (32)
- linux 杀毒软件 (32)
- linux语法 (33)
- linux博客 (33)
- linux 压缩目录 (37)
- linux 查看任务 (32)
- 制作linux启动u盘 (35)
- linux 查看存储 (29)
- linux乌班图 (31)
- linux挂载镜像 (31)
- linux 软件源 (28)
- linux题目 (30)
- linux 定时脚本 (30)
- linux 网站搭建 (28)
- linux 远程控制 (34)
- linux bind (31)