内存管理之分页
一. 前言 上文分析了内存再用户态的结构体mm_struct及各个区域映射的vm_area_struct以及32位和64位的内核态结构体,本文将基于这些结构来分析Linux的内存管理系统。内存管理系统包括虚拟内存和物理内存的分页以及虚拟内存和物理内存的映射。本文将介绍分页机制,而映射则在下文中说明。本文首先简单介绍SMP和NUMA系统,然后对物理内存的节点、区域、页结构进行分析,在此基础上剖析伙伴系统和Slub Allocator的实现原理,最后介绍页面交换。
二. 内存模型 在计算机的发展历程中,内存模型经历了平坦内存模型、SMP和NUMA三种架构。
平坦内存模型(Flat Memory Model),又称线性内存模型,在这种模式下,采取连续的物理地址和页,所以非常容易根据地址获取页号,反之亦然。此种布局非常简单,而且是线性增长,利于使用。但是随着内存需求的增大、进程数的变多、为了安全考虑,这种模型渐渐地无法满足要求。
对称多处理 SMP(Symmetric MultiProcessing),是一种多处理器的电脑硬件架构,在对称多处理架构下,每个处理器的地位都是平等的,对资源的 ...
多核心Linux内核路径优化的不二法门之-slab与伙伴系统
Linux内核的slab来自一种很简单的思想,即事先准备好一些会频繁分配,释放的数据结构。然而标准的slab实现太复杂且维护开销巨大,因此便分化 出了更加小巧的slub,因此本文讨论的就是slub,后面所有提到slab的地方,指的都是slub。另外又由于本文主要描述内核优化方面的内容,并不 是基本原理介绍,因此想了解slab细节以及代码实现的请自行百度或者看源码。
单CPU上单纯的slab下图给出了单CPU上slab在分配和释放对象时的情景序列:
可以看出,非常之简单,而且完全达到了slab设计之初的目标。
扩展到多核心CPU现在我们简单的将上面的模型扩展到多核心CPU,同样差不多的分配序列如下图所示:
我们看到,在只有单一slab的时候,如果多个CPU同时分配对象,冲突是不可避免的,解决冲突的几乎是唯一的办法就是加锁排队,然而这将大大增加延迟,我们看到,申请单一对象的整个时延从T0开始,到T4结束,这太久了。
多CPU无锁化并行化操作的直接思路-复制给每个CPU一套相同的数据结构。
不二法门就是增加“每CPU变量”。对于slab而言,可以扩展成下面的样子:
如果以为这么简单就结 ...
尽情阅读,技术进阶,详解mmap原理
1. 一句话概括mmapmmap的作用,在应用这一层,是让你把文件的某一段,当作内存一样来访问。将文件映射到物理内存,将进程虚拟空间映射到那块内存。
这样,进程不仅能像访问内存一样读写文件,多个进程映射同一文件,还能保证虚拟空间映射到同一块物理内存,达到内存共享的作用。
2. 虚拟内存?虚拟空间?其实是一个概念,前一篇对于这个词没有确切的定义,现在定义一下:
虚拟空间就是进程看到的所有地址组成的空间,虚拟空间是某个进程对分配给它的所有物理地址(已经分配的和将会分配的)的重新映射。
而虚拟内存,为啥叫虚拟内存,是因为它就不是真正的内存,是假的,因为它是由地址组成的空间,所以在这里,使用虚拟空间这个词更加确切和易懂。(不过虚拟内存这个词也不算错)
2.1 虚拟空间原理2.1.1物理内存首先,物理地址实际上也不是连续的,通常是包含作为主存的DRAM和IO寄存器
以前的CPU(如X86)是为IO划分单独的地址空间,所以不能用直接访问内存的方式(如指针)IO,只能用专门的方法(in/read/out/write)诸如此类。
现在的CPU利用PCI总线将IO寄存器映 ...
浅谈Linux内存管理机制
活学活用OOM Killer 在 Linux 系统里如果内存不足时,会杀死一个正在运行的进程来释放一些内存。
Linux 里的程序都是调用 malloc() 来申请内存,如果内存不足,直接 malloc() 返回失败就可以,为什么还要去杀死正在运行的进程呢?Linux允许进程申请超过实际物理内存上限的内存。因为 malloc() 申请的是内存的虚拟地址,系统只是给了程序一个地址范围,由于没有写入数据,所以程序并没有得到真正的物理内存。物理内存只有程序真的往这个地址写入数据的时候,才会分配给程序。
内存管理对于内存的访问,用户态的进程使用虚拟地址,内核的也基本都是使用虚拟地址
物理内存空间布局
虚拟内存与物理内存的映射
进程“独占”虚拟内存及虚拟内存划分为了保证操作系统的稳定性和安全性。用户程序不可以直接访问硬件资源,如果用户程序需要访问硬件资源,必须调用操作系统提供的接口,这个调用接口的过程也就是系统调用。每一次系统调用都会存在两个内存空间之间的相互切换,通常的网络传输也是一次系统调用,通过网络传输的数据先是从内核空间接收到远程主机的数据,然后再从内核空间复制到用户空间,供用户程序使 ...
熟读精思,熟读玩味,Linux虚拟内存管理,MMU机制,原来如此也
MMU现代操作系统普遍采用虚拟内存管理(Virtual Memory Management)机制,这需要处理器中的MMU(Memory Management Unit,内存管理单元)提供支持。
首先引入 PA 和 VA 两个概念。
PA如果处理器没有MMU,或者有MMU但没有启用,CPU执行单元发出的内存地址将直接传到芯片引脚上,被内存芯片(以下称为物理内存,以便与虚拟内存区分)接收,这称为PA(Physical Address,以下简称PA),如下图所示。
VA如果处理器启用了MMU,CPU执行单元发出的内存地址将被MMU截获,从CPU到MMU的地址称为虚拟地址(Virtual Address,以下简称VA),而MMU将这个地址翻译成另一个地址发到CPU芯片的外部地址引脚上,也就是将VA映射成PA,如下图所示。
如果是32位处理器,则内地址总线是32位的,与CPU执行单元相连(图中只是示意性地画了4条地址线),而经过MMU转换之后的外地址总线则不一定是32位的。也就是说,虚拟地址空间和物理地址空间是独立的,32位处理器的虚拟地址空间是4GB,而物理地址空间既可以大于也可以小于4G ...
硬件原理 和 分页管理
前言内存管理相对复杂,涉及到硬件和软件,从微机原理到应用程序到内核。比如,硬件上的cache,CPU如何去寻址内存,页表, DMA,IOMMU。 软件上,要知道底层怎么分配内存,怎么管理内存,应用程序怎么申请内存。
常见的误解包括:
对free命令 cache和buffer的理解。1、应用程序申请10M内存,申请成功其实并没有分配。内存其实是边写边拿。代码段有10M,并不是真的内存里占了10M。2、内存管理学习难,一是网上的资料不准确,二是学习时执行代码,具有欺骗性。看到的东西不一定真实,要想理解必须陷入Linux本身。
学习时,不要过快陷入太多细节,而要先对整个流程整个框架理解。
先理清楚脉络和主干,从硬件到最底层内存的分配算法,–>到内核的内存分配算法,–>应用程序与内核的交互,–>到内存如何做磁盘的缓存, –> 内存如何和磁盘替换。
再动手实践demo。
硬件原理 和 分页管理本文主要让大家理解内存管理最底层的buddy算法,内存为什么要分成多个Zone?
CPU寻址内存,虚拟地址、物理地址
MMU 以及RWX权限、kernel和user模式权限
内存的 ...
进程的内存消耗和泄漏
进程的内存消耗和泄漏
进程的VMA
进程内存消耗的4个概念: vss、rss、pss和uss
page fault的几种可能性, major 和 minor
应用内存泄漏的界定方法
应用内存泄漏的检测方法:valgrind 和 addresssanitizer
本节重点阐述 Linux的应用程序究竟消耗了多少内存?
一是,看到的内存消耗,并不是一定是真的消耗。
二是,Linux存在大量的内存共享的情况。动态链接库的特点:代码段共享内存,数据段写时拷贝。把一个应用程序跑两个进程,这两个进程的代码段也是共享的。
当我们评估进程消耗多少内存时,就是指在用户空间消耗的内存,即虚拟地址在0~3G的部分,对应的物理地址内存。内核空间的内存消耗属于内核,系统调用申请了很多内存,这些内存是不属于进程消耗的。
进程的虚拟地址空间VMA
task_struct里面有个mm_struct指针, 它代表进程的内存资源。pgd,代表 页表的地址; mmap 指向vm_area_struct 链表。 vm_area_struct 的每一段代表进程的一个虚拟地址空间。vma的每一段,都可能是可执行程序的某个数据段 ...
Linux IO 之 块IO流程与IO调度器
块I/O流程与 I/O调度器
一个块IO的一生:从page cache到bio 到 request
块设备层的数据结构
page和bio的关系,request 和bio的关系
O_DIRECT 和O_SYNC
blktrace , ftrace
IO调度和CFQ调度算法
CFQ和ionice
cgroup与IO
io性能测试: iotop, iostat
主要内容:从应用程序发起一次IO行为,最终怎么到磁盘,以及在这个路径上有什么trace的方法和 配置。
每次应用程序写磁盘,都是到pagecache 。三进三出 讲解 bio的一生,都是在pagecache以下。
首先,在一次普通的sys_write过程中,会触发以下的函数调用。
123456789101112131415161718192021sys_write -> vfs_write -> generic_file_write_iterPageCache: Linux通过局部性原理,使用页面缓存提高性能。1) generic_perform_write -> write_begin -& ...
Linux IO 之 文件系统的实现
Ext2/3/4 的layout
文件系统的一致性: append一个文件的全流程
掉电与文件系统的一致性
fsck
文件系统的日志
ext4 mount选项
文件系统的debug和dump
Copy On Write 文件系统: btrfs
预备知识:数据库里的transaction(事务)有什么特性?
原子性(Atomicity):事务作为一个整体被执行,包含在其中的对数据库的操作要么全部被执行,要么都不执行。
一致性(Consistency):事务应确保数据库的状态从一个一致状态转变为另一个一致状态。
持久性(Durability):一个事务一旦提交,他对数据库的修改应该永久保存在数据库中。
Ext2/3/4 的layout
如上图,任何一个文件,在硬盘上有inode、 datablocks,和一些元数据信息(- 描述数据的数据)。其中,inode的信息包括,inode bitmap 和 inode table。通过inode bitmap和block bitmap来描述具体的inode table 和data blocks是否被占 ...
Linux IO 之 文件系统的架构
本文概述:应用程序 ->read ->文件系统的代码 如何实现?当目录里面 A/B/C ,是如何找到C的全过程?文件系统如何描述文件在磁盘的哪些位置?硬链接和 符号链接的详细区别?userspace的文件系统的实现?
一切都是文件: VFS
文件系统的设计,类似 抽象基类,面向对象的思想。
虚函数都必须由底层派生出的实例实现,使用成员函数 file_operations。在linux里面的文件操作,底层都要实现file_operations,抽象出owner,write,open,release。所以,无论是字符块,还是文件系统的文件,最终操作就必须是file_operations。
例如,实现一个字符设备驱动,就是去实现file_operations。VFS_read时就会调用字符设备的file_operations。
字符设备文件、块设备文件块设备的两种访问方法,一是访问裸分区,二是访问文件系统。
当直接访问裸分区,是通过fs/block_dev.c 中的 file_operations def_blk_fops,也有read,write, ...