费炜

    1. 1、在理想情况下,Linux内核的页面分配器(page allocator)会使用伙伴系统(buddy system)算法来分配连续的物理页面。该算法将可用的物理页面划分为不同的大小类别,每个大小类别都是2的幂次方大小的页面块。例如,大小为2的幂次方的页面块可以是4KB、8KB、16KB等。当需要分配一段连续的物理页面时,页面分配器会从相应的大小类别中选择一个大小最接近需求大小的页面块,并将其分裂成两个较小的页面块,直到得到所需大小的页面块。如果没有足够大的页面块可用,则页面分配器会尝试从更大的页面块中分裂出所需大小的页面块。一旦找到了适当大小的页面块,页面分配器会将其标记为已分配,并返回其物理地址给调用者。此外,页面分配器还会跟踪已分配和未分配的页面块,以便在需要时快速找到可用的页面块。 2、在Linux内核的页面分配器中,分配掩码(gfp_mask)是一个用于指定分配内存时所需选项的掩码。其中包括了一些标志位,用于指示内存分配的要求和限制,例如分配的大小、分配的优先级等等。     在确定可以从哪些zone中分配内存时,页面分配器会根据gfp_mask中的标志位来进行判断。具体来说,它会检查以下标志位: __GFP_DMA:表示分配的内存需要在DMA区域中,即物理地址小于等于0x1000000(16MB)。 __GFP_HIGHMEM:表示分配的内存可以在HIGHMEM区域中,即物理地址大于0x1000000(16MB)。 __GFP_MOVABLE:表示分配的内存可以被移动,即不是永久性的内存分配,而是可以在需要时被移动。 __GFP_THISNODE:表示分配的内存必须在当前节点上分配,即不能跨节点分配内存。 __GFP_OTHER_NODE:表示分配的内存可以在其他节点上分配。根据gfp_mask中的标志位,页面分配器会决定从哪些zone中分配内存。     例如,如果gfp_mask包含__GFP_DMA标志位,则页面分配器只会从DMA zone中分配内存,而不会从HIGHMEM zone中分配内存。如果gfp_mask包含__GFP_MOVABLE标志位,则页面分配器会优先从MOVABLE zone中分配内存,而不会从不可移动的zone中分配内存。 3、在Linux内核中,页面分配器是按照以下顺序来扫描zone的: 当前节点的本地zone:首先,页面分配器会尝试从当前节点的本地zone中分配内存。本地zone是指与当前CPU所在节点相对应的zone,因为在同一节点上的内存分配速度比跨节点的内存分配速度更快。 当前节点的其他zone:如果当前节点的本地zone无法满足分配请求,页面分配器会尝试从当前节点的其他zone中分配内存。这些zone包括DMA、NORMAL、HIGHMEM等。 其他节点的本地zone:如果当前节点的所有zone都无法满足分配请求,页面分配器会尝试从其他节点的本地zone中分配内存。这些zone与当前CPU所在节点不同,但它们与请求分配内存的设备在同一节点上,因此分配速度也比跨节点的内存分配速度更快。 其他节点的其他zone:如果前面的所有zone都无法满足分配请求,页面分配器会尝试从其他节点的其他zone中分配内存。这些zone与当前CPU所在节点不同,并且它们与请求分配内存的设备也不在同一节点上,因此分配速度最慢。     需要注意的是,页面分配器在扫描zone时,会根据请求的分配大小和分配掩码(gfp_mask)来确定从哪些zone中分配内存。具体来说,它会根据gfp_mask中的标志位来过滤掉一些不符合要求的zone,例如__GFP_DMA标志位表示只从DMA zone中分配内存,__GFP_HIGHMEM标志位表示只从HIGHMEM zone中分配内存等等。 4、当为用户进程分配物理内存时,应该根据具体情况选择分配掩码。     一般情况下,如果分配的内存是用于进程自身的数据结构或者堆栈,那么应该选择GFP_KERNEL分配掩码。这是因为GFP_KERNEL分配掩码表示分配的内存可以被内核长期持有,不需要在内核和用户空间之间移动,因此适用于内核自身使用的内存。     如果分配的内存是用于用户进程的内存映射,那么应该选择GFP_HIGHUSER_MOVABLE分配掩码。这是因为GFP_HIGHUSER_MOVABLE分配掩码表示分配的内存可以在内核和用户空间之间移动,因此适用于用户进程使用的内存。此外,GFP_HIGHUSER_MOVABLE还表示分配的内存可以被移动到高端内存(HIGHMEM)中,这是一种物理内存不够用时的备选方案。     需要注意的是,GFP_HIGHUSER_MOVABLE分配掩码只适用于Linux内核2.6.16及以上版本。在早期版本的内核中,可以使用GFP_USER分配掩码来分配用户进程的内存映射。但是,GFP_USER分配掩码不支持内存移动,因此不适用于物理内存不够用时的情况。
    2. 1、UMA是指在一个计算机系统中,所有的处理器(CPU)都可以等效地访问系统中的所有内存。这意味着无论处理器位于何处,访问任何内存地址的开销都是相同的。UMA适用于较小的计算机系统,其中处理器数量有限。 NUMA是指在一个计算机系统中,处理器和内存被划分为多个节点(node),每个节点包含一组处理器和一部分内存。每个节点有自己的本地内存,而其他节点的内存对于该节点的处理器来说是非本地的。这意味着访问本地内存的开销较低,而访问非本地内存的开销较高。NUMA适用于大型计算机系统,其中处理器数量较多,需要更高的内存访问性能。 总结来说,UMA是指所有处理器等效访问系统中的所有内存,而NUMA是指处理器和内存被划分为多个节点,每个节点有自己的本地内存。 2、不同级别的存储结构对于CPU的访问速度是不同的。通常来说,CPU访问速度最快的是寄存器,其次是一级缓存(L1 Cache),二级缓存(L2 Cache),三级缓存(L3 Cache),最后是主存储器(DRAM)。 寄存器是CPU内部的存储器,访问速度非常快,可以在一个CPU周期内完成访问。 一级缓存(L1 Cache)是CPU内部的缓存,访问速度也非常快,通常可以在一个CPU周期内完成访问。 二级缓存(L2 Cache)和三级缓存(L3 Cache)是位于CPU和主存储器之间的缓存,访问速度比主存储器快很多,但比L1 Cache慢一些。 主存储器(DRAM)是CPU访问速度最慢的存储结构,访问速度通常需要几十个CPU周期。因此,在程序设计中,应尽可能地利用寄存器和缓存,以减少对主存储器的访问,从而提高程序的执行效率。 3、在大部分Linux系统中,内存设备的初始化一般是在BIOS或bootloader中,然后把DDR的大小传递给Linux内核,因此从Linux内核角度来看DDR,起始就是一段物理内存空间。在linux内核中,和内存硬件物理特性相关的一些数据结构主要集中在MMU(处理器中内存管理单元)中,例如页表、cache/TLB操作等。因此大部分的Linux内核中关于内存管理的数据结构都是软件的概念中,例如mm、vma、zone、page、pg_data等。linux内核中的内存管理中的数据结构错综复杂。
    3. 1、在AArch64 架构中,因为地址总线位宽最多支持48位,所以VA被划分为两个空间,每个空间最多支持256TB。 低位的虚拟地址空间位于0x00000000_00000000到0x0000FFFF_FFFFFFFF。如果虚拟地址的最高位等于0,就使用这个虚拟地址空间,并且使用TTBR0_ELx来存放页表的基地址。 高位的虚拟地址空间位于0xFFFF0000_00000000到0xFFFFFFF_FFFFFFFF。如果虚拟地址的最高位等于1,就使用这个虚拟地址空间,并且使用TTBR1_ELx来存放页表的基地址。  2、1)处理器根据页表基地址控制寄存器和虚拟地址来判断使用哪个页表基地址寄存器,是TTBR0还是TTBR1。当虚拟地址第63位(简称VA[63])为1时选择TTBR1,当VA[63]为0时选择TTBR0。页表基地址寄存器中存放着1级页表(见图中的L0页表)的基地址。 2)处理器将VA[47:39]作为L0索引,在1级页表(L0页表)中找到页表项,1级页表有512个页表项。 3)2级页表的页表项中存放着3级页表(L2页表)的物理基地址。处理器以VA[29:21]作为L2索引,在3级页表(L2页表)中找到相应的项表项,3级页表有512个页表项。 4)3级页表的页表项中存放着4级页表(L3页表)的物理基地址。处理器以VA[20:12]作为L3索引,在4级页表(L3页表)中找到相应的项表项,4级页表有512个页表项。 5)4级页表的页表项里存放着4KB页面的物理基地址让,然后加上 VA[11:0],就构成了新的物理地址,因此处理器就完成了页表的查询和翻译工作。  3、L0~L2有三种页表项类型:无效类型,块类型,页表类型。bit[0]=0为无效类型,bit[0]=1为块类型或者页表类型。bit[1]=0为块类型,bit[1]=1为页表类型。  4、 用户空间:0x00000000_00000000到0x0000FFFF_FFFFFFFF。 内核空间:0xFFFF0000_00000000到0xFFFFFFF_FFFFFFFF。
    4. 1、复杂指令集CISC的指令较多略显臃肿,而精简指令集RISC只保留了CISC中常用的少部分指令,其执行效率更高。RISC后出现,在思想上比CISC更先进。 2、在大端字节序处理器中,较高字节(MSB)存储在较低的内存地址,而较低字节(LSB)存储在较高的内存地址。因此0x12345678在大端字节序处理器的存储器中会按照0x12、0x34、0x56、0x78的顺序存储。 在小端字节序处理器中,较低字节(LSB)存储在较低的内存地址,而较高字节(MSB)存储在较高的内存地址。因此,数值0x12345678在小端字节序处理器的存储器中会按照0x78、0x56、0x34、0x12的顺序存储。 3、 在双核Cortex-A9处理器(ARM架构)中,一条存储读写指令(如LDR或STR)的执行全过程如下:      1)指令译码(Instruction Decode):处理器从指令缓存中取出待执行的存储读写指令,并对其进行译码,确定操作类型(读取还是写入)、操作数寄存器、内存地址等信息。      2)地址计算(Address Calculation):根据指令中的寄存器和偏移量等信息,计算出实际的内存地址。      3)存储器访问(Memory Access):根据计算得到的内存地址,处理器将发起对存储器的访问请求。如果是存储读指令(LDR),处理器会从内存中读取数据;如果是存储写指令(STR),处理器会将数据写入内存。      4)数据传输(Data Transfer):在存储读指令中,处理器将读取到的数据从存储器传输到指定的寄存器中。在存储写指令中,处理器将指定的寄存器中的数据传输到存储器中。      5)执行后续指令(Execute Next Instruction):完成存储读写指令的执行后,处理器会继续执行下一条指令,继续进行指令译码、执行和存储访问等操作。 4、 内存屏障(memory barrier)是为了确保在多核或多线程的并发环境下,对共享内存的读写操作具有一致性和可见性。内存屏障的作用包括:      1)顺序一致性(Sequential Consistency):内存屏障能够保证在内存屏障之前的指令的执行结果对于后续的指令是可见的,防止指令重排序导致的结果不一致性。      2)写屏障(Write Barrier):内存屏障能够确保在内存屏障之前的写操作先于内存屏障之后的写操作执行,保证写操作的顺序性。      3)读屏障(Read Barrier):内存屏障能够确保在内存屏障之前的读操作先于内存屏障之后的读操作执行,保证读操作的顺序性。      通过使用内存屏障,程序员可以显式地控制共享内存的访问顺序,确保对共享数据的操作在多核或多线程环境下的正确性和一致性。 5、 ARM体系结构定义了几条内存屏障指令,用于在多核或多线程的并发环境下确保内存访问的顺序和可见性。以下是常见的ARM内存屏障指令及其区别:      1)DMB(Data Memory Barrier):DMB指令用于确保在其之前的所有内存访问都完成后,再执行DMB之后的内存访问。它保证了内存访问的顺序性和一致性,对读写操作都起作用。      2)DSB(Data Synchronization Barrier):DSB指令用于确保在其之前的所有指令都执行完毕后,再执行DSB之后的指令。它保证了指令的顺序性和一致性,对读写操作都起作用。      3)ISB(Instruction Synchronization Barrier):ISB指令用于确保在其之前的所有指令都执行完毕后,再执行ISB之后的指令。它保证了指令的顺序性和一致性,对读写操作都起作用。 6、高速缓存(cache)是计算机系统中的一种快速存储器,用于加速对主存储器(RAM)的访问。它通过在CPU和主存之间建立一个更小但更快的存储层次结构,存储最常访问的数据和指令,以提高系统的性能。      高速缓存的工作方式如下:      1)层次结构:计算机系统中通常存在多级高速缓存,如L1、L2和L3缓存。这些缓存按照从CPU到主存的距离和容量递增的顺序排列。L1缓存是最接近CPU的,速度最快但容量最小,而L3缓存是最远离CPU的,速度相对较慢但容量较大。      2)缓存行:高速缓存将主存划分为固定大小的缓存行(cache line),通常是64字节或128字节。缓存行是缓存的最小单位,用于存储从主存中读取的数据块。      3)缓存映射:缓存使用一种映射机制将主存中的数据映射到缓存行中。最常见的映射方式是直接映射、组相联映射和全相联映射。这些映射方式决定了数据在缓存中的位置和访问方式。      4)缓存命中和缓存失效:当CPU需要读取数据时,首先会检查缓存中是否存在该数据。如果数据在缓存中找到(命中),则称为缓存命中,CPU可以直接从缓存中读取数据,提高访问速度。如果数据不在缓存中(失效),则需要从主存中读取,并将其存储到缓存中以供后续访问。      5)替换策略:当缓存已满且需要将新的数据存储到缓存中时,需要选择一个缓存行进行替换。常见的替换策略有最近最少使用(LRU)、随机替换等,目的是选择最有可能被未来访问的数据进行替换。      通过以上工作方式,高速缓存能够提供快速的数据访问,减少对主存的访问延迟,提高计算机系统的整体性能。 7、全关联映射(Full-Associative Mapping):在全关联映射中,主存中的每个数据块都可以映射到缓存中的任意一个缓存行。这意味着任何一个数据块都可以存储在任何一个缓存行中,没有固定的映射关系。      直接映射(Direct Mapping):在直接映射中,主存中的每个数据块只能映射到缓存中的一个特定缓存行。数据块的映射位置是通过数据块的地址与缓存行数取模来确定的。这意味着每个数据块只能存储在缓存中的一个固定位置。      组相联映射(Set-Associative Mapping):组相联映射是全关联映射和直接映射的折中方式。缓存被分为多个组,每个组包含多个缓存行。主存中的每个数据块可以映射到一个组中的任意一个缓存行。数据块的映射位置是通过数据块的地址与组数取模来确定的。            现代处理器普遍使用组相联的高速缓存映射方式的原因如下:      灵活性:组相联映射提供了一定的灵活性,允许数据块在多个缓存行中选择映射位置。这样可以减少缓存冲突,提高缓存的利用率和性能。      减少冲突:直接映射容易导致缓存冲突,即多个数据块需要映射到同一个缓存行,导致频繁的替换和缓存失效。组相联映射通过增加组的数量,减少了冲突的可能性,提高了缓存的命中率。      折中方案:全关联映射虽然可以消除冲突,但需要更复杂的硬件支持,增加了成本和功耗。直接映射虽然简单,但容易产生冲突。组相联映射在性能和复杂度之间找到了一个折中的方案。      综上所述,组相联映射方式在现代处理器中被广泛使用,因为它提供了较高的灵活性和性能,同时也能够有效地减少缓存冲突带来的性能损失。
    5. 个人信息无误,确认可以完成阅读计划和打卡任务

最近访客

< 1/1 >

统计信息

已有11人来访过

  • 芯积分:18
  • 好友:--
  • 主题:--
  • 回复:5

留言

你需要登录后才可以留言 登录 | 注册


现在还没有留言