首页 > 编程知识 正文

linux内核makefile(linux文件系统有哪些)

时间:2023-05-03 22:32:22 阅读:73979 作者:4933

Linux存储器结构Node首先将存储器划分成节点,每个节点与系统中的一个处理器相关联,在内核中由pg_data_t的

实例.系统中的每个节点链接到以NULL结尾的pgdat_list链表,每个节点使用pg_data_tnode_next字段链接到下一节。 UMA结构的计算机(如PC )只使用一个静态pg作为contig_page_data

区域节点还分为不同的区域,主要用于管理不同的内存空间。 那为什么要把节点分成Zone呢?

1. ISA总线上的直接内存存储DMA处理器有严格的限制。他们只能寻址RAM的前16MB。

2 .在具有大内存的现代32位计算机上,CPU无法直接访问所有物理地址。 这是因为线性地址空间太小,内核无法将所有物理内存直接映射到线性地址空间。

分区Zone内存范围:

因为高端内存位于32位计算机上,所以内存可以访问的最大容量逻辑上只有2^32=4G。 但实际上,32位计算机的内存有4G以上。 在linux上,用户状态下可访问的内存为0-3G,内核状态下可访问的内存为3G-4G。 因为只有4G逻辑地址,物理内存超过4G,所以有高端内存。 高端内存不固定具有128米逻辑地址映射的物理地址。 因此,可以利用这128米的非固定逻辑地址访问所有物理地址。 由于64位计算机上不存在高端内存,因此我们将不再详细讨论。

Page页是存储数据的基本单元,内存中的所有数据都以页为单位存储。

CPU型号UMA型号定义:统一内存访问(通常简称UMA )表示所有物理内存共享均匀,即处理器访问它们的时间相同。 UMA也称为统一寻址技术或统一内存访问。

由于SMP模型中的所有资源(CPU、IO和内存)都是共享的,因此SMP的哪些部分可能成为瓶颈,最受限制的是内存。 由于每个CPU必须通过同一内存总线访问同一内存资源,因此随着CPU数量的增加,内存访问冲突迅速增加,最终导致CPU资源的浪费,CPU性能的有效性大大降低。 实验证明,SMP服务器CPU利用率最高的是2~4个CPU。 SMP是UMA模型的实现。

NUMA模型定义:非统一内存访问,简称NUMA,是为具有多处理器的计算机设计的内存,内存访问时间取决于内存相对于处理器的相对位置。 在NUMA中,处理器访问其本地存储器的速度比非本地存储器稍快。

NUMA服务器的基本特点是具有多个CPU模块,每个CPU模块由四个不同的CPU组成,具有独立的本地内存、I/O插槽等。 每个CPU都可以通过互连模块(如Crossbar Switch )在节点之间进行连接和信息交换,从而访问整个系统的内存。 这是NUMA系统和MPP系统的重要区别。 很明显,本地内存访问速度要比远程内存(系统中其他节点的内存)访问速度快得多。 这也是对NUMA的不一致性存储访问的由来。 根据这一特点,为了更好地发挥系统的性能,在开发APP应用时需要尽量减少不同CPU模块之间的信息交换。 每个CPU和一个内存构成一个节点。

NUMA模型和Mysql问题由于Mysql数据存储在磁盘上且对磁盘的访问速度较慢,因此Innodb有一个称为buffer-pool的大缓存空间,通常占用系统至少1G的内存。 当然,这可以配置,但性能比缓冲池高。NUMA的CPU通常使用相邻Node的内存,因此速度会快一些,但是当相邻Node的内存耗尽时,NUMA的碎片这样,mysql访问内存中的数据时会变慢。

分割机制是在8086处理器诞生之前,内存寻址方式是直接访问物理地址。 886处理器将地址总线扩展到20位,以寻址1M的内存空间。 但是,出现了尴尬的问题。 ALU的宽度只有16位。 也就是说,ALU无法计算20位地址。 为了解决这个问题,引入了细分机制,登上了历史舞台。

为了支持段,8086处理器设有4个段寄存器。 CS、DS、SS、ES。 每个段寄存器为16位,访问存储器的指令的地址也为16位。 然而,在发送到地址总线之前,CPU将其加到某个段寄存器内的值上。 这里,由于段寄存器值对应于20位地址总线的前16位,所以相加值实质上是在16位的存储器地址、即段内偏移值的前12位上加上段寄存器的前16位,后4位则是由此形成20位的实际地址,实现从16位的存储器地址到20位的实际地址的转换,或者“映射”。

实际分段机制的寻址过程:

在实际寻址处理中,CPU获取32位的逻辑地址,CPU确定该逻辑地址在本地段描述符表(LDT或GDT )中,选择要在寄存器中获取的段选择器,并基于偏移来确定该段选择器可以说分段机制在linux上没有使用,所以页面很容易就带走了。

分页机制

分页机制是linux的内存管理机制,所以会详细的介绍。
分页的基本方法是将地址空间人为地等分成某一个固定大小的页;每一页大小由硬件来决定,或者是由操作系统来决定(如果硬件支持多种大小的页)。目前,以大小为4KB的分页是绝大多数PC操作系统的选择.

页:为了更高效和更经济的管理内存,线性地址被分为以固定长度为单位的组,成为页。页内部连续的线性地址空间被映射到连续的物理地址中。这样,内核可以指定一个页的物理地址和对应的存取权限,而不用指定全部线性地址的存取权限。这里说页,同时指一组线性地址以及这组地址包含的数据。

页框

页框:分页单元把所有的 RAM 分成固定长度的页框(page frame)(有时叫做物理页)。每一个页框包含一个页(page),也就是说一个页框的长度与一个页的长度一致。页框是主存的一部分,因此也是一个存储区域。区分一页和一个页框是很重要的,前者只是一个数据块,可以存放在任何页框或磁盘中。

页表

页表:把线性地址映射到物理地址的数据结构称为页表(page table)。

寻址过程

在32位的机器上,一般会把32位划分成三个段,就是目录、页表、偏移量。
在实际寻址的时候,CPU接受到一个32位的逻辑地址,根据然后从CR3寄存器中拿到Page Directory在内存中的首地址,再根据逻辑地址中的目录拿到Page Table在内存中的首地址,跟根据逻辑地址中的Table拿到Offset Table中的首地址,最后根据偏移量拿到最终的物理地址。说了这么多其实就说了一个重点,就是从寄存器中拿到一个首地址,再根据相应的偏移量拿到下一个表的首地址。所以目录、页表、偏移量都是相对的偏移量,不用死记。

那么问题来了,为什么寻址要用三级页表呢?为什么不直接用一个页表寻址呢?
因为如果只使用一级页表,那么每个页的大小是2^12=4K,一级页表的个数就是2^20,每个条目(也叫PDE)4个字节,那么维护一个页表就需要4M,每个进程都需要一个页表来维护,如果计算机有100个进程,就需要400M的大小。如果采用多级页表可以把20分为两个10位,也就是10+10+12,这样当二级页表里面整个页表都没有使用到时,就不用建立二级页表和三级页表,这样就大大节省了页表占用的内存空间。

64位分页

64位机器寻址过程:

其实64位的寻址过程和32位的相比,只不过是多了几级页表。

页面置换算法

https://www.cnblogs.com/fkissx/p/4712959.html

总结

在分页机制中,我们能看出来系统采用了时间换空间的方法,因为采用了多级页表节省了内存空间导致每次寻址至少要进行三次,因为每次寻址都会在内存中找到相应的页表,最后寻址到物理内存。

PAE技术

前面提到了,32位的机器最大的能支持的内存只有2^32=4G,但是我们会常常看到一些32的机器可以加内存到8G、16G,这就是PAE技术的出现。
早期Intel处理器从80386到Pentium使用32位物理地址,理论上,这样可以访问4GB的RAM。然而,大型服务器需要大于4GB的RAM来同时运行数以千计的进程,近几年来这对Intel造成了压力,所以必须扩展32位80x86所支持的RAM容量。
Intel通过在它的处理器上把管脚数从32增加到36已经满足了这些需求,可以寻址64GB。同时引入了一种新的分页机制PAE(Physical Address Extension,物理地址扩展)把32位线性地址转换为36位物理地址才能使用所增加的物理内存,通过设置CR4的第5位来开启对PAE的支持。引入PAE就是为了访问大于4GB的RAM,线性地址仍然是32位,而物理地址是36位。
PAE寻址每页4K大小:

PAE寻址每页2M大小:

为什么32位的逻辑地址可以映射到36位的物理地址?
因为开启PAE分页的话,每个进程会保存多套页表,这样一来,进程可以根据需要改变CR3中的值去访问不同的页表。也就是说,进程在运行过程中会修改CR3的值从而指向不同的页表来访问不同的物理地址。

TLB技术

在两级页表中,每次访问内存至少都要经过三次内存访问才能拿到物理地址,这样一来效率会变得很低,所以就有了TLB(Translation Lookaside Buffer)技术。TLB是MMU(负责把虚拟地址转换成物理地址)一块高速缓存,用来缓存页号(32位地址中的前20位称为页号)对应的数据(包括物理地址和访问控制信息)。

CPU把一个虚拟地址交给MMU。MMU查找TLB是否有该虚拟地址的缓存,若有则TLB hit,直接从TLB中拿到页框的物理地址。若TLB miss,执行TTW(Translation Table Walk简称TTW,就是从页表中查找物理地址),然后更新TLB。查询Cache中是否有Page数据,上面拿到只不过是页框的物理地址,还要拿到真正的数据。若Cache hit则从Cache中拿到数据,否则从内存中拿到数据,更新Cache。 PCID技术

因为每个CPU有一个TLB,所以每次不同的进程被CPU选中执行的时候,TLB里面的数据都要被刷新掉,所以刚开始进程运行的时候TLB里面的数据都是空的,等运行时间长了,TLB才会慢慢被填满,TLB的命中率才会变高。这样一来TLB的性能就不是很好,因为每次都要重新开始添加数据,所以就有了PCID技术。
每个进程都要一个自己的PCID来唯一表示该进程,这样一来,TLB存储数据的时候会加上PCID这个标识来表示该条数据是哪个进程的,这样一来就不需要每次切换进程的时候都刷新TLB,但PCID技术在linux很后面的版本才开始支持的,因为PCID技术同样存在问题。
当我们更新一个进程的TLB缓存的时候,相应的其他CPU里面的TLB也需要做更新,这样一来性能并没有很好的提升。

伙伴系统

在linux中,前面分页机制只是建立的从虚拟地址到物理地址的映射关系,但还要考虑物理内存如何分配,伙伴系统的产生页解决了linux系统的外碎片的问题。
伙伴系统把内存按照2^n次幂分为大小不同的内存块,然后使用链表把各个内存块链接起来。

举例:假设RAM有1M,当系统需要一个63K的内存块时,首先会去找2^6的链表中找是否有空闲的内存,若没有则去2^7的链表中去找,依次类推,当找到2^20链表中时,就会把分裂2^20中的一个内存块假设位a1,a2,那么a1和a2就互为伙伴,a1继续分裂,a2就加入到2^19=512k的链表中,a1分裂至2^n-1<63K<=2^n。

slab机制

slab是Linux操作系统的一种内存分配机制。其工作是针对一些经常分配并释放的对象,如进程描述符等,这些对象的大小一般比较小,如果直接采用伙伴系统来进行分配和释放,不仅会造成大量的内碎片,而且处理速度也太慢。而slab分配器是基于对象进行管理的,相同类型的对象归为一类(如进程描述符就是一类),每当要申请这样一个对象,slab分配器就从一个slab列表中分配一个这样大小的单元出去,而当要释放时,将其重新保存在该列表中,而不是直接返回给伙伴系统,从而避免这些内碎片。slab分配器并不丢弃已分配的对象,而是释放并把它们保存在内存中。当以后又要请求新的对象时,就可以从内存直接获取而不用重复初始化。

版权声明:该文观点仅代表作者本人。处理文章:请发送邮件至 三1五14八八95#扣扣.com 举报,一经查实,本站将立刻删除。