iis服务器助手广告广告
返回顶部
首页 > 资讯 > 操作系统 >Linux内存映射指的是什么
  • 601
分享到

Linux内存映射指的是什么

2023-06-28 13:06:48 601人浏览 独家记忆
摘要

linux内存映射指的是什么,很多新手对此不是很清楚,为了帮助大家解决这个难题,下面小编将为大家详细讲解,有这方面需求的人可以来学习下,希望你能有所收获。 内存映射就是用户空间的一段内存区域映射到内核空间,映射成功后,用户对这段内存区域的修

linux内存映射指的是什么,很多新手对此不是很清楚,为了帮助大家解决这个难题,下面小编将为大家详细讲解,有这方面需求的人可以来学习下,希望你能有所收获。

内存映射就是用户空间的一段内存区域映射到内核空间,映射成功后,用户对这段内存区域的修改可以直接反映到内核空间,相反,内核空间对这段区域的修改也直接反映用户空间。

一. 内存映射原理

由于所有用户进程总的虚拟地址空间比可用的物理内存大很多,因此只有最常用的部分才与物理页帧关联。这不是问题,因为大多数程序只占用实际可用内存的一小部分。在将磁盘上的数据映射到进程的虚拟地址空间的时,内核必须提供数据结构,以建立虚拟地址空间的区域和相关数据所在位置之间的关联,linux软件系统多级页表映射机制 Linux内存映射指的是什么 注:上图中的最右侧page,代表软件层面的页帧率,并非真正的物理内存。真正的物理内存也会分页,名称为页框,页帧到页框的转换则是有MMU自动完成的。以下讨论均不考虑MMU(MMU完成的工作作为黑箱看待)。

二. Linux的页表实现

一级页表

一个32位逻辑地址空间的计算机系统,总地址4G字节,页大小为4KB,则有4G/4K = 1M个页,那么页表中需要存放1M个条目(每个条目代表一个页)。假设每个条目占4B,则需要4M字节内存来存放页表。 每个进程都需要管理所有4G内存,所以每个进程都要4M来存放页表,极其浪费。

二级页表

Linux内存映射指的是什么 虚拟地址到物理页地址的转换过程如下:

  • 结合在CR3寄存器中存放的页目录(page directory, PGD)的这一页的物理地址,再加上从虚拟地址中抽出高10位叫做页目录表项(内核也称这为pgd)的部分作为偏移, 即定位到可以描述该地址的pgd;

  • 从该pgd中可以获取可以描述该地址的页表的物理地址,再加上从虚拟地址中抽取中间10位作为偏移, 即定位到可以描述该地址的pte;

  • 在这个pte中即可获取该地址对应的页的物理地址, 加上从虚拟地址中抽取的最后12位,即形成该页的页内偏移, 即可最终完成从虚拟地址到物理地址的转换。

其中 虚拟地址的组成: DIRECTORY [22:31] 可表示1024个页目录(PGD) TABLE[12:21] 可表示1024个页表(PTE) OFFSET[22:31] 可表示4096个物理内存 因此最大映射物理内存大小为 102410244096 = 4G/Byte

三级页表

当X86引入物理地址扩展(Pisycal Addrress Extension, PAE)后,可以支持大于4G的物理内存(36位),但虚拟地址依然是32位,原先的页表项不适用,它实际多4 bytes被扩充到8 bytes,这意味着,每一页现在能存放的pte数目从1024变成512了(4k/8)。相应地,页表层级发生了变化,Linus新增加了一个层级,叫做页中间目录(page middle directory, PMD) 办法是针对使用2级页表的架构,把PMD抽象掉,即虚设一个PMD表项。这样在page table walk过程中,PGD本直接指向PTE的,现在不了,指向一个虚拟的PMD,然后再由PMD指向PTE。这种抽象保持了代码结构的统一。 该方法其实就是在原有虚拟地址组成中的几位作为PMD索引: |31| —–PGD—–|29|—–PMD—–| 20|—–PTE—–|11|—-OFFSET|—–|0|

四级页表

硬件在发展,3级页表很快又捉襟见肘了,原因是64位CPU出现了, 比如X86_64, 它的硬件是实实在在支持4级页表的。它支持48位的虚拟地址空间(不过Linux内核最开始只使用47位)。如下: Linux内存映射指的是什么 需注意软件的页表映射依赖于硬件所支持的映射级别,目前ARM64支持2/3/4 级映射,假如ARM配置的映射级别为3级,那么linux的映射表中 PGD=PUD,即实际为三级映射。

文件索引节点

设文件索引节点中有7 个地址项,其中4 个地址项是直接地址索引,2 个地址项是一级间 接地址索引,1 个地址项是二级间接地址索引,每个地址项大小为4B,若磁盘索引块和磁盘数据块 大小均为256B,请计算可表示的单个文件最大长度。

每个索引块上可以存放的索引项为256B/4B=26 =64个。直接索引的数据块有4 块;两个一级 间接索引指向的数据块有2×26=27 = 128个;一个二级间接索引指向的数据块有1×26×26=212 个。所以单个文件最大可以有4+27+212(=4228)个数据块。 文件大小为 4228×256B=(4+27+212)×28=33KB+1MB=1057KB

三. 虚拟空间分布

linux将整个虚拟空间分为用户空间与内核空间,且每个用户进程均占用一份完整的用户虚拟空间 Linux内存映射指的是什么 上图为64位系统的虚拟地址空间分布用户空间大小为512G,32位系统用户空间结束地址为0xc0000000,大小为3G.

用户空间

用户虚拟地址空间大小为3G,每个应用程序均独占完整的3G虚拟空间。这里应该可以看出,真是的物理内存不可能等于虚拟内存,因为同一时间会有众多进程运行,每一进程均拥有3G内存,而实际物理内存不可能满足所有进程的需求。此时上面说到的内存映射便发挥了作用。

  • 一般而言,一个进程虽然拥有3G虚拟内存访问权限,但是实际需要的内存可能很少,另外一个进程大部分的主体,比如代码段,只读数据段等并不需要实时驻留在内存中,因为这些内容在大多数时间是“死的”。因此内存映射的第一个作用就是: 只会将某一进程此刻需要的内存大小映射到物理内存,其它暂时不需要的内容交换到硬盘存储即可。当进程需要使用在硬盘中的内容或者需要动态申请内存时,操作系统会利用缺页操作,触发一次内存映射,将另外的物理内存映射进虚拟内存,供程序使用,这样对于进程而言,则认为内存总是够用的。

  • 各个进程均拥有3G虚拟内存,那么操作系统是如何做到各进程所使用的实际物理内存不会互相占用呢?实际上,各个进程均有自己的内存映射表。任意一个时刻,在一个CPU上只有一个进程在运行。所以对于此CPU来讲,在这一时刻,整个系统只存在一个4GB的虚拟地址空间,这个虚拟地址空间是面向此进程的。当进程发生切换的时候,虚拟地址空间也随着切换。由此可以看出,每个进程都有自己的虚拟地址空间,只有此进程运行的时候,其虚拟地址空间才被运行它的CPU所知。在其它时刻,其虚拟地址空间对于CPU来说,是不可知的。所以尽管每个进程都可以有4 GB的虚拟地址空间,但在CPU眼中,只有一个虚拟地址空间存在。虚拟地址空间的变化,随着进程切换而变化。

内核空间

Linux内存映射指的是什么 内核空间具有相对独立的特性。即内核的虚拟地址空间范围是自己独有的,不与任何用户进程共享(内核实质也是一个进程)。这样可保证内核空间的安全性。但是由于内核虚拟地址空间较小0xc000000~0xFFFFFFFF 仅有1G大小,这一大小往往小于实际的物理内存,因此内核空间需要额外的方式来访问到所有物理内存。

Linux内存映射指的是什么 由上图可知,内核空间又分为三大部分: ZONE_DMA :0XC000000 + 16M 线性映射区 该区域的物理页面专门供I/O设备的DMA使用。之所以需要单独管理DMA的物理页面,是因为DMA使用物理地址访问内存,不经过MMU,并且需要连续的缓冲区,所以为了能够提供物理上连续的缓冲区,必须从物理地址空间专门划分一段区域用于DMA。例如dma_alloc_coherent函数获取的内存就是ZONE_DMA内存 ZONE_NORMAL :0XC100000 + 880M 线性映射区 该区域的物理页面是内核能够直接使用的,比如内核程序中代码段、全局变量以及kmalloc获取的堆内存等。从此处获取内存一般是连续的,但是不能太大。 ZONE_HIGHMEM :0xF8000000 + 28M 该区域比较负责又可细分为三部分:

  • 非连续内存区 非连续内存分配是指将物理地址不连续的页框映射到线性地址连续的线性地址空间,主要应用于大容量的内存分配。采用这种方式分配内存的主要优点是避免了外部碎片,而缺点是必须打乱内核页表,而且访问速度较连续分配的物理页框慢。函数vmalloc即是通过该部分虚拟地址来映射物理内存。

  • 永久内核映射区 如果是通过 alloc_page() 获得了高端内存对应的 page,如何给它找个线性空间? 内核专门为此留出一块线性空间,从 PKMAP_BASE 到 FIXADDR_START ,用于映射高端内存。在 2.6内核上,这个地址范围是 4G-8M 到 4G-4M 之间。这个空间起叫”内核永久映射空间”或者”永久内核映射空间”。这个空间和其它空间使用同样的页目录表,对于内核来说,就是 swapper_pg_dir,对普通进程来说,通过 CR3 寄存器指向。通常情况下,这个空间是 4M 大小,因此仅仅需要一个页表即可,内核通过来 pkmap_page_table 寻找这个页表。通过 kmap(),可以把一个 page 映射到这个空间来。由于这个空间是 4M 大小,最多能同时映射 1024 个 page。因此,对于不使用的的 page,及应该时从这个空间释放掉(也就是解除映射关系),通过 kunmap() ,可以把一个 page 对应的线性地址从这个空间释放出来。

  • 临时固定映射区 fixmap和pkmap的最大区别是fixmap不会被阻塞,因此可以在中断上下文中使用。实际上每次fixmap都是可以成功执行映射的,原因是fixmap不会动态申请映射,它是以固定映射的方式进行的,如果我们传入了一个映射type,它就肯定会执行对应的映射,而把之前的映射冲刷掉,因此fixmap的映射关系是靠内核代码来进行维护的,所以内核需要保证同一个映射区不被重复使用,从而出现错误。

前 面我们解释了高端内存的由来。 Linux将内核地址空间划分为三部分ZONE_DMA、ZONE_NORMAL和ZONE_HIGHMEM,高端内存HIGH_MEM地址空间范围为 0xF8000000 ~ 0xFFFFFFFF(896MB~1024MB)。那么如内核是如何借助128MB高端内存地址空间是如何实现访问可以所有物理内存?

当内核想访问高于896MB物理地址内存时,从0xF8000000 ~ 0xFFFFFFFF地址空间范围内找一段相应大小空闲的逻辑地址空间,借用一会。借用这段逻辑地址空间,建立映射到想访问的那段物理内存(即填充内核PTE页面表),临时用一会,用完后归还。这样别人也可以借用这段地址空间访问其他物理内存,实现了使用有限的地址空间,访问所有所有物理内存。 例 如内核想访问2G开始的一段大小为1MB的物理内存,即物理地址范围为0×80000000 ~ 0x800FFFFF。访问之前先找到一段1MB大小的空闲地址空间,假设找到的空闲地址空间为0xF8700000 ~ 0xF87FFFFF,用这1MB的逻辑地址空间映射到物理地址空间0×80000000 ~ 0x800FFFFF的内存。

四.内核空间与用户空间交互

系统调用

系统调用的可实现进程由用户态切换至内核态。但是通过上面分析已经了解,用户进程与内核进程相互分离的,那么在进行系统调用时参数传递是如何实现的呢? 解决这一办法的思路是:数据拷贝。因为无论是用户地址空间还是内核地址空间均为虚拟地址空间,因此在做参数传递时,只需要将在用户地址空间存放的参数拷贝至内核地址空间即可。完成拷贝的函数就是大家熟知的copy_from_user() &copy_to_user(). Linux内存映射指的是什么 上图表示某一用户进程将一组数据传递给内核,内核经过处理后将数据返回至用户进程。该过程涉及到数据在两块内存区域的转移:用户虚拟内存地址对应的物理内存与内核虚拟内存地址对应的物理内存。

mmap函数

函数原型:

 void *mmap{  void *addr; //映射区首地址,传NULL  size_t length; //映射区的大小   //会自动调为4k的整数倍   //不能为0   //一般文件多大,length就指定多大  int prot; //映射区权限   //PROT_READ 映射区比必须要有读权限   //PROT_WRITE   //PROT_READ | PROT_WRITE  int flags; //标志位参数   //MAP_SHARED 修改了内存数据会同步到磁盘   //MAP_PRIVATE 修改了内存数据不会同步到磁盘  int fd; //要映射的文件对应的fd  off_t offset;  //映射文件的偏移量,从文件的哪里开始操作   //映射的时候文件指针的偏移量   //必须是4k的整数倍   //一般设置为0

用户空间mmap调用 用户空间读写文件时,需经过内核,数据拷贝多了一次。通过mmap函数,可以建立用户虚拟空间到文件所在物理页的直接映射建立该映射后,可以像直接操作内存一样读写文件(比如读写数组),减少一次用户到内核的数据拷贝。

     fd = open(argv[1], O_RDWR);          mmaped = (char *)mmap(NULL, sb.st_size, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);          close(fd);     mmaped[5] = '$';     msync(mmaped, sb.st_size, MS_SYNC) 1234567

Linux内存映射指的是什么 内核空间mmap实现 直接打开一个磁盘文件,实际是调用了文件系统提供的mmap版本。但是对于开发linux驱动的工程师来说,需自己实现对应设备文件的mmap函数,例如framebuffer这种设备需要较高频率大数据读写,因此不能容忍内核空间到用户空间的数据拷贝,因此驱动需开发自己的mmap函数供用户进程调用,驱动mmap实现流大致为:

  1. 通过kmalloc, get_free_pages, vmalloc等分配一段虚拟地址

  2. 如果是使用kmalloc, get_free_pages分配的虚拟地址,那么使用virt_to_phys()将其转化为物理地址,再将得到的物理地址通过”phys>>PAGE_SHIFT”获取其对应的物理页面帧号。或者直接使用virt_to_page从虚拟地址获取得到对应的物理页面帧号。 如果是使用vmalloc分配的虚拟地址,那么使用vmalloc_to_pfn获取虚拟地址对应的物理页面的帧号。

  3. 对每个页面调用SetPageReserved()标记为保留才可以。

  4. 通过remap_pfn_range为物理页面的帧号建立页表,并映射到用户空间。

      //内存分配  buffer = (unsigned char *)kmalloc(PAGE_SIZE,GFP_KERNEL);    //将该段内存设置为保留  SetPageReserved(virt_to_page(buffer));  //得到物理地址  phys = virt_to_phys(buffer);  //将用户空间的一个vma虚拟内存区映射到以page开始的一段连续物理页面上  remap_pfn_range(vma,                  vma->vm_start,                  phys >> PAGE_SHIFT,//第三个参数是页帧号,由物理地址右移PAGE_SHIFT得>到                  vma->vm_end - vma->vm_start,                  vma->vm_page_prot) 123456789101112

mmap函数并非实现用户空间与内核空间的交互,而是用户空间试图绕过内核空间,直接操作物理页

四. 完整的linux系统下内存分布图

Linux内存映射指的是什么

Linux有哪些版本

Linux的版本有:Deepin、ubuntuKylin、Manjaro、LinuxMint、Ubuntu等版本。其中Deepin是国内发展最好的Linux发行版之一;UbuntuKylin是基于Ubuntu的衍生发行版;Manjaro是基于Arch的Linux发行版;LinuxMint默认的Cinnamon桌面类似windows XP简单易用;Ubuntu则是以桌面应用为主的Linux操作系统。

看完上述内容是否对您有帮助呢?如果还想对相关知识有进一步的了解或阅读更多相关文章,请关注编程网操作系统频道,感谢您对编程网的支持。

--结束END--

本文标题: Linux内存映射指的是什么

本文链接: https://www.lsjlt.com/news/319544.html(转载时请注明来源链接)

有问题或投稿请发送至: 邮箱/279061341@qq.com    QQ/279061341

本篇文章演示代码以及资料文档资料下载

下载Word文档到电脑,方便收藏和打印~

下载Word文档
猜你喜欢
  • Linux内存映射指的是什么
    Linux内存映射指的是什么,很多新手对此不是很清楚,为了帮助大家解决这个难题,下面小编将为大家详细讲解,有这方面需求的人可以来学习下,希望你能有所收获。 内存映射就是用户空间的一段内存区域映射到内核空间,映射成功后,用户对这段内存区域的修...
    99+
    2023-06-28
  • Linux内核反向映射机制是什么
    本篇内容主要讲解“Linux内核反向映射机制是什么”,感兴趣的朋友不妨来看看。本文介绍的方法操作简单快捷,实用性强。下面就让小编来带大家学习“Linux内核反向映射机制是什么”吧!1.反向映射的发展实际上在早期的Linux内核版本中是没有反...
    99+
    2023-06-15
  • Linux端口映射的方法是什么
    这篇文章主要介绍“Linux端口映射的方法是什么”,在日常操作中,相信很多人在Linux端口映射的方法是什么问题上存在疑惑,小编查阅了各式资料,整理出简单好用的操作方法,希望对大家解答”Linux端口映射的方法是什么”的疑惑有所帮助!接下来...
    99+
    2023-06-28
  • C#.Net通信共享内存映射文件是什么
    这篇文章主要讲解了“C#.Net通信共享内存映射文件是什么”,文中的讲解内容简单清晰,易于学习与理解,下面请大家跟着小编的思路慢慢深入,一起来研究和学习“C#.Net通信共享内存映射文件是什么”吧!节点通信存在两种模型:共享内存(Share...
    99+
    2023-06-30
  • windows映射网络驱动器指的是什么
    本文小编为大家详细介绍“windows映射网络驱动器指的是什么”,内容详细,步骤清晰,细节处理妥当,希望这篇“windows映射网络驱动器指的是什么”文章能帮助大家解决疑惑,下面跟着小编的思路慢慢深入,一起来学习新知识吧。映射网络驱动器是什...
    99+
    2023-07-01
  • 云服务器内网映射是什么
    云服务器内网映射指的是将本地内网IP映射到云服务器的IP地址或公网IP地址范围内,从而实现跨云计算平台的访问。通常,云服务器通过内部的IP来映射用户访问,而云服务器本身也将访问地址映射到内部的IP,以便在云服务器的本地内网范围内实现用户的功...
    99+
    2023-10-26
    内网 服务器
  • Linux主机名映射的方法是什么
    这篇文章主要讲解了“Linux主机名映射的方法是什么”,文中的讲解内容简单清晰,易于学习与理解,下面请大家跟着小编的思路慢慢深入,一起来研究和学习“Linux主机名映射的方法是什么”吧!1. 查看主机名: hostname&nbs...
    99+
    2023-06-28
  • linux中映像文件指的是什么
    今天小编给大家分享一下linux中映像文件指的是什么的相关知识点,内容详细,逻辑清晰,相信大部分人都还太了解这方面的知识,所以分享这篇文章给大家参考一下,希望大家阅读完这篇文章后有所收获,下面我们一起来了解...
    99+
    2023-04-21
    linux
  • Linux内核指的是什么
    今天就跟大家聊聊有关Linux内核指的是什么,可能很多人都不太了解,为了让大家更加了解,小编给大家总结了以下内容,希望大家根据这篇文章可以有所收获。内核属于操作系统的核心部分,它具有操作系统基本的功能,主要负责管理系统的内存、进程、设备驱动...
    99+
    2023-06-28
  • 云服务器内网映射是什么意思
    云服务器内网映射指的是将不同的服务器通过网络相互连接,形成一个虚拟的网络,使数据在这个虚拟网络中进行交换和处理。 具体来说,对于一个 A 的服务器来说,它可以通过 B 的服务器向 A 发送数据,然后 A 的服务器通过 B 的服务器接收数据...
    99+
    2023-10-26
    内网 服务器
  • Hibernate的集合映射是什么
    这期内容当中小编将会给大家带来有关Hibernate的集合映射是什么,文章内容丰富且以专业的角度为大家分析和叙述,阅读完这篇文章希望大家可以有所收获。POJOs如下:Customer类---->customer表Order类对应---...
    99+
    2023-06-17
  • java映射的概念是什么
    在Java中,映射(Map)是一种数据结构,用于存储键值对(key-value pairs)的集合。每个键(key)都是唯一的,而值...
    99+
    2023-08-23
    java
  • 云服务器内网映射是什么意思呀
    云服务器内网映射指的是在同一台云服务器上部署多个虚拟网络设备(VPN)。这些VPN设备允许管理员将企业内网和互联网通过VPN设备连接起来,以实现远程访问、移动办公等目标。 这种技术通常用于公司内部部署的数据中心,以满足内部员工对速度和稳定...
    99+
    2023-10-26
    内网 服务器
  • 云服务器内网映射是什么意思啊
    云服务器内网映射指的是将本地主机的文件系统映射到云服务器的内存中。这样的映射可以确保用户的访问权限只能通过特定的API接口才能访问云服务器资源,而不会影响到云服务器的内部网络配置和其他功能。 例如,当一个用户登录到一个云服务器时,他们可以...
    99+
    2023-10-26
    内网 服务器
  • javascript中内存指的是什么
    这篇文章主要介绍了javascript中内存指的是什么的相关知识,内容详细易懂,操作简单快捷,具有一定借鉴价值,相信大家阅读完这篇javascript中内存指的是什么文章都会有所收获,下面我们一起来看看吧。...
    99+
    2022-10-19
  • 云主机端口映射到内网的方法是什么
    云主机端口映射到内网的方法有两种常见的方式:1. 端口转发(Port Forwarding):通过在路由器上进行端口映射设置,将外部...
    99+
    2023-09-14
    云主机
  • 内存容量是指什么
    内存容量是指计算机系统中可用于存储和处理数据的存储空间大小,它对计算机的性能、功能和多任务处理能力有着重要影响。计算机中,数据和指令需要存储在内存中才能被处理器读取和执行,内存容量决定了计算机可以同时存储和处理的数据量。本教程操作系统:Wi...
    99+
    2023-08-14
  • linux内核移植指的是什么
    这篇“linux内核移植指的是什么”文章的知识点大部分人都不太理解,所以小编给大家总结了以下内容,内容详细,步骤清晰,具有一定的借鉴价值,希望大家阅读完这篇文章能有所收获,下面我们一起来看看这篇“linux内核移植指的是什么”文章吧。在li...
    99+
    2023-06-29
  • 内存xmp指的是什么意思
    这篇文章给大家分享的是有关内存xmp指的是什么意思的内容。小编觉得挺实用的,因此分享给大家做个参考,一起跟随小编过来看看吧。xmp是Intel提出的内存认证标准,是Intel用在内存上的一种优化技术,是一个内存配置文件,用于让内存自动超频。...
    99+
    2023-06-14
  • Java内存分配指的是什么
    这篇文章主要介绍“Java内存分配指的是什么”的相关知识,小编通过实际案例向大家展示操作过程,操作方法简单快捷,实用性强,希望这篇“Java内存分配指的是什么”文章能帮助大家解决问题。概念1、内存是计算机的重要原件,临时存储区域,作用是运行...
    99+
    2023-06-30
软考高级职称资格查询
编程网,编程工程师的家园,是目前国内优秀的开源技术社区之一,形成了由开源软件库、代码分享、资讯、协作翻译、讨论区和博客等几大频道内容,为IT开发者提供了一个发现、使用、并交流开源技术的平台。
  • 官方手机版

  • 微信公众号

  • 商务合作