内存管理FAQ(freshground )

来源:互联网 发布:游戏优化器 编辑:程序博客网 时间:2024/05/01 01:35

Q:什么是mm?
A:指的是内存管理(memory management)。是内核中的一套软件机制,用于有效管理内存的使用。

Q:内存管理的软件实现了什么功能?
A:1) 进程的保护,即进程向内存管理请求的物理页,由内存管理系统负责,不会将同一物理页(共享页面除外)映射到不同进程的虚地址空间。 
2) 虚存的实现,允许所有进程使用的内存总量大于实际物理内存总量。 

Q:MMU与TLB的功能?
A:TLB是MMU的核心部件,用于实现页表转换,将虚拟地址转换成实地址。
对i386而言,MMU会根据CR3中的地址(注意,这个地址是物理地址)指定的页表目录一级一级去查询,在下面情况会抛出缺页中断: 
* 页目录为空(NULL) 
* 页表项为空,或者对应物理页不再内存中。 
* 权限不满足,比如写带只读属性的页;用户态的代码访问特权属性的页。

Q:什么是cache?
A:对于硬件,指的是一块SRAM,由于它的访问速度比较快,所以将经常访问的数据放在这块SRAM中,必要时才写回到主存储器中,这样可以提高CPU的使用效率;对于软件,指的是主存储器中的一块空间(即缓冲区),当CPU与慢速IO进行交换数据时,先将数据放在这块内存空间中,等系统空闲时,才真正与IO进行数据交换。比如说,当用户请求 将一块数据写入磁盘时,内核会先将数据放在缓冲区中,等到系统空闲或真正有必要马上就写数据时,内核才会执行磁盘操作,将数据写到磁盘上。在读内核源代码时,经常会看到"xx_cache_xx"之类的字眼,其实基本上都是内存缓冲区。

Q:什么是COW?
A:它实际上指的是“写时拷贝(Copy On Write)”,其主要目的是提高内存管理的效率。当内核创建进程时,为其分配的虚拟页面并没有被真正映射到物理内存上,而是被映射到一块不可写(页表项上的标志为“只读”)的内存上(对于子进程,映射的是其父进程的物理空间),当该进程要往里面写东东时,就会产生一个页面异常。在异常处理函数中会将这块虚拟页面映射到它应该映射的物理页面上。

Q:什么是伙伴(buddy)系统?
A:用伙伴算法(一般的数据结构书中都有讲解)管理物理内存的系统。它分配的物理内存大小都是页(4K)的整数倍。


Q:什么是slab分配器?
A:指的是内存管理单元先向伙伴系统申请一块较大的物理内存(批发),然后再将其肢解成许多小碎片分配给需要的进程(零售)。当有的进程需要分配一小块内存(一般都小于一个页面,或不是页的整数倍),用来存放某个数据结构(如vm_area_struct),都可以向slab申请零售。

Q:什么是足印(footprint)?
A:足印(footprint)是指要完成某个工作,需要访问的缓存(一般指L1 DATA CACHE 或TLB)项的个数。例如,完成的工作是:访问B. 但要访问B对象首先必须从A对象中获得B的指针,如果A,B在一个页面中,那么只需要在TLB踏上一个"足印"就可以了,否则需要踏上两个“足印”;进一步的,如果A,B对象在同一个16或者32个字节对齐的空间里,那么在L1 DATA CACHE里只需要踏上一个足印就可以了。
一般完成某项工作在各种缓存上的足印越少,引起缓存失去命中的可能性就越小,缓存和内存之间的交互就越小,因此访问速度就越快。另外见讨论。


Q:什么是active_mm?
A:active_mm表示当前与CPU关联的分页结构,对于普通进程,它等于mm,对于内核线程,它等于上一次用户进程的mm。

Q:什么是e820?
A:INT15的0xe820(=AX)号BIOS调用获取系统物理内存的配置表(e820map)。

+========================================================================================================================================+

Q:源代码中的gfp_xxx,gfp是什么的缩写? 
A:是Get Free Page。
-- zeuszj 

Q:cache_cache里的slab的大小是不是一个page?
A:cache_cache是专用slab管理器队列的头,在 kmem_cache_sizes_init() 的过程中cache_cache->gfporder应该一直都是0,所以是一个page;而这个队列中的各个slab管理器(kmem_cache_t)的gfporder都不一定等于0,所以不一定是一个page。 

Q:kmalloc(size)返回的是物理地址,还是虚拟地址,为什么? 
A:是虚拟地址。因为该地址是经过映射后的地址。 
-- ytang 

Q:怎样得到kmalloc分配的内存地址的实际物理地址?
A:kmalloc分配了一段物理上连续的内存空间,可以通过virt_to_phys()将返回的虚地址转换为一个物理地址,或者通过virt_to_bus()转换为一个IO总线地址。
--jkl

Q:malloc()在内核中对应的函数是什么? 
A:用户程序中使用的malloc是Glibc包装过的函数,它通过brk系统调用分配虚存给用户。
--xshell

Q:分配虚存空间有了mmap和munmap为什么还需要sys_brk?
A:其实,brk调用的系统调用是sys_brk,他通过mmap进行实现(可以这样认为)。但是,对于用户调用的malloc,free等函数,是由glibc实现的。即:库首先通过brk向系统申请一块大的虚存块,然后,这块内存由库进行管理,就是堆的管理由库实现。实际上,调用brk的目的无非是告诉内核这块内存的引用是合法,只有这样,缺页中断才能进 
行下去。 
如果没有这种机制,则可能导致应用程序对应的虚存块太多,使系统性能不佳。如果堆的管理在应用层进行,则没有这种坏处。
-- xiongjs 

Q:请教一个术语--“堆”。
A:堆(heap)是在代码段(和全局数据区)上方的那段空间(bss),通过malloc分配的内存都是在堆里的。 

Q:malloc在程序结束不free会怎样? 
A:进程退出后,与进程相关的所有资源都被内核无条件释放,进程一般不会在内核中造成资源溢漏。 malloc()基于进程的虚存映射区域,进程退出后,随着虚存映射的撤消,它所占用的物理页面也随之释放。 

A:page->age与__PAGE_OLD标志位有何关系? 
Q:和交换有关。 
PAGE_OLD实际上是cpu自己设定的,每次被访问的页面会被cpu设为~PAGE_OLD,age是linux设定的,初始根据PAGE_OLD,然后不断改动。
--lucian_yao

A:我想阅读mm部分的源代码,从哪个函数入手?
Q:page_alloc.c和slab.c是内核用于分配内存的,可以先看。
--lucian_yao

+========================================================================================================================================+

Q:为什么要用copy_from_user(),而不直接读用户空间呢?
A:copy_from_user()主要完成两个任务:检查用户地址的有效性和建立修正表。检查用户地址的有效性主要是为了防止用户进程访问了内核或其他非法地址;建立修正表主要为中断处理中发生的缺页异常提供补救方法。具体见讨论。

Q:什么是字对齐(word aligned)?
A:也就是访问的地址值可以被4整除,相应的“半字对齐”是指访问的地址值可以被2整除。

Q:用kmalloc分配的内存是否会被swapper交换出去吗?
A:不会。

Q:3G+phy-mem和物理内存之间是一一映射的,而0-3G的用户空间最终也肯定是映射到物理内存,那么我有一点不明白的是物理内存是如何同时映射到两段空间的?
A:是通过页表映射得到的。
--xshell

Q:void * kmalloc (size_t size, int flags)中参数的含义?
A:参数size表明要申请的内存大小(以byte为单位),flags参数表示申请内存的类型,这些类型可以是: 
GFP_KERNEL - 申请内存的进程可能被放入等待队列,也可能被交换到swap分区,但是仍然是使用最为普遍,也是分配到内存的最可靠的方式。 
GFP_USER - 用于为用户分配内存,也可能被放入等待队列,是优先级很低的一种请求方式。 
GFP_ATOMIC - 分配的时候不会被放入等待队列,如果没有分配到内存,则立即返回。多用在中断处理内部。 
GFP_DMA - 这个标志表明分配的内存用于DMA。对于不同的平台这有不同的含义,在i386平台上,意味着这些内存必须来自于物理内存的最初16M。
--arfankai

Q:如何实现内存映射?比如说我的pci卡上有一块内存,然后我要将这段内存映射到机器内存里面来进行读写,应该怎么做呢?
A:void * __ioremap(unsigned long phys_addr, size_t size, unsigned long flags) 
void __iounmap(void *addr) 
源代码在ioremap.c中。
--calfe 

Q:分配虚存空间有了mmap和munmap为什么还需要sys_brk? 
A:其实,brk调用的系统调用是sys_brk,他通过mmap进行实现(可以这样认为)。但是,对于用户调用的malloc,free等函数,是由glibc实现的。即:库首先通过brk向系 
统申请一块大的虚存块,然后,这块内存由库进行管理,就是堆的管理由库实现。实际上,调用brk的目的无非是告诉内核这块内存的引用是合法,只有这样,缺页中断才能进 
行下去。 
如果没有这种机制,则可能导致应用程序对应的虚存块太多,使系统性能不佳。如果堆的管理在应用层进行,则没有这种坏处。
--xiongjs

Q:进程所分配得到的物理内存全部是通过系统调用和异常服务程序得到的么?
A:如果是用户进程的话,应该是这样的。

Q:Linux的mm部分经常出现bitmap这个词,而程序中bitmap描述的一般都是一个unsigned long型的变量,我不知道bitmap比较形象的含义是什么?
A:比如说内存位图:每一位表示一个页面(4K),则一个字节表示8个页面(32K)的属性。这些位置1表示被占用,置0表示free,可以被分配。

Q:伙伴系统一次可分配的连续内存最大为多大?kmalloc呢?
A:伙伴系统一次可分配的连续内存最大为2M;kmalloc最大只能分配128K。

+========================================================================================================================================+

Q:有什么方法能够读取系统物理内存(指内容, 不是大小)? 
A:
1) 
cat /proc/meminfo 
cat /proc/iomem 

2) 
open("/dev/mem",O_RDONLY) 
lseek,read,write 
--xshell

Q:既然内存分配为2^k个页面,哪,释放是不是也要2^k个页面呢?
A:是的。
--haierb

Q:noncontiguous memory究竟指的是内存的哪一块?
A:它不代表哪一块特定的内存,vm_struct只不过映射一些随机的不连续的内存块,不过这些内存块的大小必须是4096的倍数。

Q:A20是什么东西?看setup里有enable a20, 这是个什么东西?
A:是intel系列cpu 实模式下的第20位地址线,实模式下上位内存能否被访问,它有否被激活是关键。由于它被激活后cpu可以访问高于1兆的内存地址,所以linux的引导代 
码用它来测试i386以上的cpu是否进入了保护模式。
--野枫

Q:linux内核中一个有哪些段?
A:内核里有代码段, 数据段, 都是0到4G, 还有为每个进程分配的TSS段, 236字节。
--yangke

Q:flush_tlb_xxx()这类函数都是干什么用的?
A:冲刷TLB,使TLB中的内容无效。实现方法(即先把cr3中的内容读出,再写入)是:
"movl %%cr3, %0; # flush TLB/n" 
"movl %0, %%cr3;/n" 
cr3中装的是全局页表的基地址,对于i386,只要这个寄存器被重新赋值,tlb中的内容就全被作废。

原创粉丝点击