0

0

深入理解 Linux 内核:虚拟地址空间与物理内存的映射关系

PHPz

PHPz

发布时间:2024-06-01 08:04:17

|

1271人浏览过

|

来源于ITcool

转载

显存映射

化学显存合称为寻址,动态随机访问显存(DRAM)。只有内核才可以直接访问数学显存。

Linux内核给每位进程都提供了一个独立的虚拟地址空间,但是这个地址空间是连续的。这样,进程就可以很便捷地访问显存,更准确地说是访问虚拟显存。虚拟地址空间的内部又被分为内核空间和用户空间两部份。

linux 用户分配空间_linux磁盘分配空间_linux分配用户权限

进程在用户态时,只能访问用户空间显存;只有步入内核态后,才可以访问内核空间显存。其实每位进程的地址空间都包含了内核空间,但这种内核空间,虽然关联的都是相同的化学显存,也就是共享动态链接库、共享显存等。当进程切换到内核态后,就可以很便捷地访问内核空间显存。

并不是所有的虚拟显存就会分配化学显存,只有这些实际使用的虚拟显存才分配化学显存,但是分配后的化学显存,是通过显存映射来管理的。显存映射,虽然就是将虚拟显存地址映射到化学显存地址。为了完成显存映射,内核为每位进程都维护了一张页表,记录虚拟地址与化学地址的映射关系。

linux磁盘分配空间_linux分配用户权限_linux 用户分配空间

页表实际上储存在CPU的显存管理单元MMU中,这样,正常情况下,处理器就可以直接通过硬件,找出要访问的显存。而当进程访问的虚拟地址在页表中查不到时,系统会形成一个缺页异常,步入内核空间分配化学显存、更新进程页表,最后再返回用户空间,恢复进程的运行。

CPU上下文切换中的TLB(TranslationLookasideBuffer,转译后备缓冲器)是MMU中页表的高速缓存。因为进程的虚拟地址空间是独立的linux是什么系统,而TLB的访问速率又比MMU快得多,所以,通过降低进程的上下文切换,降低TLB的刷新次数,就可以提升TLB缓存的使用率,从而提升CPU的显存访问性能。

MMU规定了一个显存映射的最小单位,也就是页,一般是4KB大小。这样,每一次显存映射,都须要关联4KB或则4KB整数倍的显存空间。

4KB大小的页,会造成整个页表会显得十分大,例如32位系统4GB/4KB=100多万个页表项。为了解决页表项过多的问题,Linux提供了两种机制,也就是多级页表和大页(HugePage)。

linux分配用户权限_linux 用户分配空间_linux磁盘分配空间

多级页表就是把显存分成区块来管理,将原先的映射关系改成区块索引和区块内的偏斜。因为虚拟显存空间一般只用了极少一部份,这么,多级页表就只保存那些使用中的区块,这样就可以大大地减低页表的项数。Linux用四级页表来管理显存页,虚拟地址被分为5个部份,前4个表项用于选择页,而最后一个索引表示页内偏斜。

linux 用户分配空间_linux磁盘分配空间_linux分配用户权限

大页,就是比普通页更大的显存块,常见的大小有2MB和1GB。大页一般用在使用大量显存的进程上,例如Oracle、DPDK等。

通过这种机制,在页表的映射下,进程就可以通过虚拟地址来访问数学显存了。

虚拟显存空间分布

最上方的是内核空间,下方的是用户空间显存,用户空间又被分成多个不同的段

linux磁盘分配空间_linux分配用户权限_linux 用户分配空间

用户空间显存,从低到高分别是5种不同的显存段

1、只读段,包括代码和常量等

linux磁盘分配空间_linux 用户分配空间_linux分配用户权限

2、数据段,包括全景变量等

3、堆,包括动态分配的显存,从低地址开始向下下降

4、文件映射段,包括动态库,共享显存等,从高地址开始向上下降

5、栈,包括局部变量和函数调用的上下文等,栈的大小是固定的,通常是8M

这5个显存段中,堆和文件映射的显存是动态分配的,例如使用C标准库的malloc或mmap(),就可以分别在堆和文件映射段动态分配显存。64位系统的显存分布也是类似的,只是显存空间要大的多

显存分配与回收

malloc()是C标准库提供的显存分配函数,对应到系统调用上,有两种实现方法,即brk()和mmap()。

linux磁盘分配空间_linux 用户分配空间_linux分配用户权限

对小块显存(大于128K),C标准库使用brk()来分配,也就是通过联通堆顶的位置来分配显存。这种显存释放后并不会立即归还系统,而是被缓存上去,这样就可以重复使用。

linux磁盘分配空间_linux分配用户权限_linux 用户分配空间

对大块显存(小于128K),则直接使用显存映射mmap()来分配,也就是在文件映射段找一块空闲显存分配出去。

这两种方法的异同点:

brk()方法的缓存,可以降低缺页异常的发生,提升显存访问效率。不过,因为这种显存没有归还系统,在显存工作忙碌时,频繁的显存分配和释放会导致显存碎片。

mmap()方法分配的显存,会在释放时直接归还系统,所以每次mmap就会发生缺页异常。在显存工作忙碌时,频繁的显存分配会造成大量的缺页异常,使内核的管理负担减小。这也是malloc只对大块显存使用mmap的诱因。

须要注意的是:当这两种调用发生后,虽然并没有真正分配显存。这种显存,都只在首次访问时才分配,也就是通过缺页异常步入内核中,再由内核来分配显存。

整体来说,Linux使用伙伴系统来管理显存分配。上面我们谈到过,这种显存在MMU中以页为单位进行管理,伙伴系统也一样linux漏洞扫描,以页为单位来管理显存,而且会通过相邻页的合并,降低显存碎片化(例如brk方法导致的显存碎片)。

但在实际系统运行中,会有大量比页还小的对象,如不到1K,倘若为它们也分配单独的页,会浪费大量的显存,那该如何分配显存呢?

在用户空间linux 用户分配空间,malloc通过brk()分配的显存,在释放时并不立刻归还系统,而是缓存上去重复借助。

在内核空间,Linux则通过slab分配器来管理小显存。你可以把slab看成建立在伙伴系统上的一个缓存,主要作用就是分配并释放内核中的小对象。

linux 用户分配空间_linux磁盘分配空间_linux分配用户权限

显存回收:对显存来说,假如只分配而不释放,还会导致显存泄露,甚至会用尽系统显存。所以,在应用程序用完显存后,还须要调用free()或unmap(),来释放那些不用的显存。其实,系统也不会任由某个进程用完所有显存。在发觉显存紧张时,系统还会通过一系列机制来回收显存,例如下边这三种形式:

(1)回收缓存,例如使用LRU(LeastRecentlyUsed)算法,回收近来使用最少的显存页面。

(2)回收不常访问的显存,把不常用的显存通过交换分区(Swap)直接讲到c盘中。Swap虽然就是把一块c盘空间当作显存来用。它可以把进程暂时不用的数据储存到c盘中(这个过程称为换出),当进程访问那些显存时,再从c盘读取这种数据到显存中(这个过程称为换入)。Swap把系统的可用显存变大了,但一般只在显存不足时,就会发生Swap交换,而且因为c盘读写的速率远比显存慢,Swap会造成严重的显存性能问题。

(3)杀害进程,显存紧张时系统就会通过OOM(OutofMemory,内核的一种保护机制),直接杀掉占用大量显存的进程.。OOM监控进程的显存使用情况,但是使用oom_score为每位进程的显存使用情况进行评分:

一个进程消耗的显存越大,oom_score就越大;

一个进程运行占用的CPU越多,oom_score就越小。

这样,进程的oom_score越大,代表消耗的显存越多,也就越容易被OOM杀害,进而可以更好保护系统。

其实,为了实际工作的须要,管理员可以通过/proc文件系统,自动设置进程的oom_adj,因而调整进程的oom_score。oom_adj的范围是[-17,15],数值越大,表示进程越容易被OOM杀害;数值越小,表示进程越不容易被OOM杀害,其中-17表示严禁OOM。如用下边的命令,你就可以把sshd进程的oom_adj调小为-16,这样,sshd进程就不容易被OOM杀害。

echo-16>/proc/$(pidofsshd)/oom_adj

linux磁盘分配空间_linux 用户分配空间_linux分配用户权限

linux磁盘分配空间_linux 用户分配空间_linux分配用户权限

buffer和cache

free命令中buffer和cache都表示缓存,但用途不一样

1、Buffer,是内核缓冲区用到的显存,对应的是/proc/meminfo中的Buffer值

2、Cache,是内核页缓存和Slab用到的显存,对应的是/proc/meminfo中的Cache和SReclaimable之和

简单来说,Buffer是对c盘数据的缓存,而Cache是文件数据的缓存,它们既会用在读恳求中,也会用在写恳求中。

cache(缓存)从CPU角度考虑,是为了提升cpu和显存之间的数据交换速率而设计的,比如平时看到的一级缓存、二级缓存、三级缓存。cpu在执行程序所用的指令和读数据都是针对显存的,也就是从显存中取得的。因为显存读写速率慢,为了提升cpu和显存之间数据交换的速率,在cpu和显存之间降低了cache,它的速率比显存快linux 用户分配空间,而且造价高,又因为在cpu内不能集成太多集成电路,所以通常cache比较小,之后intel等公司为了进一步提升速率,又降低了二级cache,甚至五级cache,它是按照程序的局部性原理而设计的,就是cpu执行的指令和访问的数据常常在集中的某一块,所以把这块内容装入cache后,cpu就不用在访问显存了,这就提升了访问速率。其实若cache中没有cpu所须要的内容,还是要访问显存的。

从显存读取与c盘读取角度考虑,cache可以理解为操作系统为了更高的读取效率,更多的使用显存来缓存可能被再度访问的数据。

缓冲(buffers)是为了提升显存和硬碟(或其他I/O设备)之间的数据交换的速率而设计的。把分散的写操作集中进行,降低c盘碎片和硬碟的反复寻道,因而提升系统性能。linux有一个守护进程定期清空缓冲内容(即写入c盘),也可以通过sync命令自动清空缓冲。

简单来说,buffer是即即将被写入c盘的,而cache是被从c盘中读下来的。buffer是由各类进程分配的,被用在如输入队列等方面。一个简单的反例如某个进程要求有多个数组读入,在所有数组被读入完整之前,进程把原本读入的数组置于buffer中保存。

cache常常被用在c盘的I/O恳求上,假如有多个进程都要访问某个文件,于是该文件便被弄成cache以便捷上次被访问,这样可提升系统性能。

相关专题

更多
java基础知识汇总
java基础知识汇总

java基础知识有Java的历史和特点、Java的开发环境、Java的基本数据类型、变量和常量、运算符和表达式、控制语句、数组和字符串等等知识点。想要知道更多关于java基础知识的朋友,请阅读本专题下面的的有关文章,欢迎大家来php中文网学习。

1468

2023.10.24

堆和栈的区别
堆和栈的区别

堆和栈的区别:1、内存分配方式不同;2、大小不同;3、数据访问方式不同;4、数据的生命周期。本专题为大家提供堆和栈的区别的相关的文章、下载、课程内容,供大家免费下载体验。

392

2023.07.18

堆和栈区别
堆和栈区别

堆(Heap)和栈(Stack)是计算机中两种常见的内存分配机制。它们在内存管理的方式、分配方式以及使用场景上有很大的区别。本文将详细介绍堆和栈的特点、区别以及各自的使用场景。php中文网给大家带来了相关的教程以及文章欢迎大家前来学习阅读。

572

2023.08.10

堆和栈的区别
堆和栈的区别

堆和栈的区别:1、内存分配方式不同;2、大小不同;3、数据访问方式不同;4、数据的生命周期。本专题为大家提供堆和栈的区别的相关的文章、下载、课程内容,供大家免费下载体验。

392

2023.07.18

堆和栈区别
堆和栈区别

堆(Heap)和栈(Stack)是计算机中两种常见的内存分配机制。它们在内存管理的方式、分配方式以及使用场景上有很大的区别。本文将详细介绍堆和栈的特点、区别以及各自的使用场景。php中文网给大家带来了相关的教程以及文章欢迎大家前来学习阅读。

572

2023.08.10

页面置换算法
页面置换算法

页面置换算法是操作系统中用来决定在内存中哪些页面应该被换出以便为新的页面提供空间的算法。本专题为大家提供页面置换算法的相关文章,大家可以免费体验。

403

2023.08.14

oracle清空表数据
oracle清空表数据

当表中的数据不需要时,则应该删除该数据并释放所占用的空间。本专题为大家提供oracle清空表数据的相关文章,帮助大家解决该问题。

264

2023.08.16

Oracle中declare的使用
Oracle中declare的使用

Oracle DECLARE语句是PL/SQL编程语言中用于声明变量、常量、游标或异常的关键字。它的主要作用是在程序中定义这些对象,以便在后续的代码中使用。DECLARE语句的语法简单明了,可以根据需要声明多个对象。通过使用这些声明的对象,可以进行各种操作,如计算、查询数据库、处理异常等 。

203

2023.09.15

PS使用蒙版相关教程
PS使用蒙版相关教程

本专题整合了ps使用蒙版相关教程,阅读专题下面的文章了解更多详细内容。

12

2026.01.19

热门下载

更多
网站特效
/
网站源码
/
网站素材
/
前端模板

精品课程

更多
相关推荐
/
热门推荐
/
最新课程
SQL 教程
SQL 教程

共61课时 | 3.5万人学习

Java 教程
Java 教程

共578课时 | 47.9万人学习

oracle知识库
oracle知识库

共0课时 | 0人学习

关于我们 免责申明 举报中心 意见反馈 讲师合作 广告合作 最新更新
php中文网:公益在线php培训,帮助PHP学习者快速成长!
关注服务号 技术交流群
PHP中文网订阅号
每天精选资源文章推送

Copyright 2014-2026 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号