美文网首页
Linux内存, since 2020-11-09

Linux内存, since 2020-11-09

作者: Mc杰夫 | 来源:发表于2020-11-09 21:37 被阅读0次

(2020.11.09 Mon)
简单的说,内存就是一个数据货架,其最小的存储单位大多是一个字节Byte。内存用内存地址(Memory address)来为每个字节的数据顺序编号。内存地址从0开始,每次增加1。线性增加的存储器地址称为线性地址(linear address)。用十六进制来表示内存地址,如0x1A010CB0,其中的'0x'表示十六进制,后面跟着的就是内存地址的十六进制数。

内存地址的编号有上限。地址空间的范围和地址总线(address bus)的位数直接有关。CPU通过地址总线进来向内存地址说明想要存取数据的地址。32位CPU有32个针脚可以传输地址信息。每个针脚对应了一位。该针脚的高电压表示1,否则是0。内存能把这32位电压高低信息转换成32位二进制数,从而知道CPU想要的是哪个位置的数据。32位地址空间就是从0x00000000到0xFFFFFFFF。

内存的存储单元采用了随机读取存储器(Random Access Memory, RAM),其中的随机读取指的是存储器的读取时间和数据所在位置无关。相反,磁带和录像带就不是随机读取。随机读取的特性是内存成为主存储器的关键因素

内存的存储空间,可以满足内核的运行需求,还能支持运行中的进程,即其存储能力和计算机运行状态的数据总量相当。

虚拟内存

在Linux下,进程不能直接读写内存中地址为0x1位置的数据,进程中能访问的地址只能是虚拟内存地址(virtual memory address)。操作系统会把虚拟内存地址翻译成真实的内存地址。这种内存管理方式,叫做虚拟内存(virtual memory)

每个进程有自己的一套虚拟内存地址,用来给自己的进程空间标号。从功能上来,虚拟内存地址和内存一样,都是为数据提供索引。进程间的虚拟内存地址相互独立,因此两个进程完全可能有一样的虚拟内存地址。

虚拟内存和物理内存有一定的对应关系,对进程某个虚拟内存地址的操作,会被CPU翻译成对某个具体内存地址的操作。

应用程序对物理内存地址一无所知,只能和虚拟内存沟通进行数据读写。程序中表达的内存地址,都是虚拟内存地址。进程对虚拟内存的操作会被系统翻译成对物理内存地址的操作。该转换/翻译过程由操作系统负责。C语言中表达的内存地址,都是虚拟内存地址。用下面指令打印变量地址

int v =0;
printf('%p', (void*)&v);

借助虚拟内存,系统可以保障进程空间的独立性。只要操作系统把两个进程的进程空间对应到不同的内存区域,进程间就不可能互相篡改对方的数据,进程出错的可能性就大大减少了。

有了虚拟内存,内存共享也变得简单。操作系统把同一物理内存区对应到多个进程空间,不需要任何数据复制,多个进程就可以看到相同的数据。内核共享库的映射,就是通过这种方式进行的。每个进程空间最初一部分的虚拟内存地址,都对应了物理内存中预留给内核的空间,所以进程即可共享同一套内核数据。IPO中的共享内存,也有赖于虚拟内存地址。

内存分页Paging

虚拟内存和物理内存的对应关系,被保存在一个表中,为了翻译速度足够快,这个表就需要放在内存中。为了减少这个对应表的占用空间,Linux使用内存分页(paging)来管理虚拟内存和物理内存的对应关系。

所谓分页,就是以更大尺寸的单位页(page)来管理内存。Linux中通常页的大小是4KB。用下面指令获得当前页的大小

$getconf PAGE_SIZE

返回4096,即表示每个内存也存放4096个字节,i.e., 4KB。物理内存和虚拟内存都被分割成页。

无论是物理内存还是虚拟内存,一页之内的地址都是连续的。一个虚拟页和物理页对应起来,页内的数据就可以按顺序一一对应。两种地址的末尾部分应该完全相同。4096 = 2^{12},所以地址的最后12位对应关系天然城里,这部分被成为偏移量(offset),表达了该字节在页内的位置。地址的前一部分是页编号,操作系统只需记录页编号的对应关系,所以对应关系的数字就缩减为原来的4096分之一。

多级分页

内存分页管理制度的关键在于管理进程空间页和物理页的对应关系。操作系统把对应关系记录在分页表(page table)中。为保证查询速度,分页表也会保存在内存中 。分页表实现的最简单方式就是把所有对应关系记录到同一个线性列表中。

单一分页表需要给每一个虚拟页预留一条记录的位置。对任一个 进程,其进程空间真正用到的地址都相当有限。进程中的堆栈很少会沾满进程空间,如果使用连续分页表,很多条目没有真正用到。Linux的分页表采取多层的数据结构,减少所需空间。

地址被分为页编号和偏移量两个部分,用单层的分页表记录页编号部分的对应关系。对于多层分页表来说,进一步分割页编号为两个或更多的部分,用两层或更多层的分页表来记录对应关系。

多层分页表就好像完整的电话号码分成区号,同一地区的电话号和对应人名记录在同一个本子上,再用一个上级本子记录区号和各个小本子的对应关系。若某个区号没有被使用,则上级本子上把该区号标记为空。同样,一级分页表中某个记录为空,则该记录开头的虚拟地址段没有使用,相应的二级表就不需要存在了。多层分页表占据的空间比单层分页少了很多。

多层分页表的另一个优势。单层分页表必须存在于连续的内存空间,而多层分页表的二级表,可以散布于内存的不同位置,可以利用零碎空间来存储分页表。

Reference

1 Vamei,周昕梓著,树莓派开始,玩转Linux,中国工信出版社,电子工业出版社,2018

相关文章

网友评论

      本文标题:Linux内存, since 2020-11-09

      本文链接:https://www.haomeiwen.com/subject/hfyrbktx.html