四时宝库

程序员的知识宝库

理解xv6——2.5 代码:物理内存分配器

The allocator’s data structure is a free list of physical memory pages that are available for allocation. Each free page’s list element is a struct run (3115) . Where does the allocator get the memory to hold that data structure? It store each free page’s run structure in the free page itself, since there’s nothing else stored there. The free list is protected by a spin lock (3119-3123) . The list and the lock are wrapped in a struct to make clear that the lock protects the fields in the struct. For now, ignore the lock and the calls to acquire and release; Chapter 4 will examine locking in detail.

分配器的数据结构是可用于分配的物理内存页的空闲列表。每个空闲页面的列表元素是一个struct run(3115)。分配器从哪里获得内存来填充该数据结构呢?它将每个空闲页的run结构存储在空闲页本身中,因为那里没有存储任何其他内容。空闲列表由自旋锁(spin lock)(3119-3123)保护。列表和锁包装在结构中,以明确锁保护结构中的字段。现在,忽略锁以及获取和释放的调用;第4章将详细讨论锁定。


The function main calls kinit1 and kinit2 to initialize the allocator (3131) . The reason for having two calls is that for much of main one cannot use locks or memory above 4 megabytes. The call to kinit1 sets up for lock-less allocation in the first 4 megabytes, and the call to kinit2 enables locking and arranges for more memory to be allocatable.

main ought to determine how much physical memory is available, but this turns out to be difficult on the x86. Instead it assumes that the machine has 224 megabytes (PHYSTOP) of physical memory, and uses all the memory between the end of the kernel and PHYSTOP as the initial pool of free memory. kinit1 and kinit2 call freerange to add memory to the free list via per-page calls to kfree. A PTE can only refer to a physical address that is aligned on a 4096-byte boundary (is a multiple of 4096), so freerange uses PGROUNDUP to ensure that it frees only aligned physical addresses. The allocator starts with no memory; these calls to kfree give it some to manage.

函数main调用kinit 1和kinit 2来初始化分配器(3131)。有两个调用的原因是,对于大多数main,不能使用超过4兆字节的锁或内存。对kinit 1的调用在前4兆字节中设置无锁分配,对kinit 2的调用启用锁定并安排更多的内存可分配。

main应该确定有多少物理内存可用,但这在x86上很困难。相反,它假设机器有224兆字节(PHYSTOP)的物理内存,并使用内核结束和PHYSTOP之间的所有内存作为初始的空闲内存池。kinit 1和kinit 2通过对kfree的每页调用来调用freerange以将存储器添加到空闲列表。PTE只能引用在4096字节边界上对齐的物理地址(是4096的倍数),因此freerange使用PGROUNDUP来确保它只释放对齐的物理地址。分配器启动时没有内存;这些对kfree的调用给予它一些管理。


The allocator refers to physical pages by their virtual addresses as mapped in high memory, not by their physical addresses, which is why kinit uses P2V(PHYSTOP) to translate PHYSTOP (a physical address) to a virtual address. The allocator sometimes treats addresses as integers in order to perform arithmetic on them (e.g., traversing all pages in kinit), and sometimes uses addresses as pointers to read and write memory (e.g., manipulating the run structure stored in each page); this dual use of addresses is the main reason that the allocator code is full of C type casts. The other reason is that freeing and allocation inherently change the type of the memory.

分配器通过映射到高内存中的虚拟地址而不是物理地址来引用物理页面,这就是kinit使用P2 V(PHYSTOP)将PHYSTOP(物理地址)转换为虚拟地址的原因。分配器有时将地址视为整数以便对它们执行算术(例如,遍历Kinit中的所有页),并且有时使用地址作为指针来读取和写入存储器(例如,操纵存储在每个页面中的run结构);地址的这种双重使用是分配器代码充满C类型强制转换的主要原因。另一个原因是释放和分配本质上改变了内存的类型。


The function kfree (3164) begins by setting every byte in the memory being freed to the value 1. This will cause code that uses memory after freeing it (uses ‘‘dangling references’’) to read garbage instead of the old valid contents; hopefully that will cause such code to break faster. Then kfree casts v to a pointer to struct run, records the old start of the free list in r->next, and sets the free list equal to r. kalloc removes and returns the first element in the free list.

函数kfree(3164)通过将存储器中被释放的每个字节设置为值1来开始。这将导致在释放内存后使用内存的代码(使用“悬空引用”)读取垃圾信息,而不是旧的有效内容;从而希望这样的代码更快崩溃。然后kfree将v强制转换为指向struct run的指针,在r->next中记录空闲列表的旧开始,并将空闲列表设置为等于r。kalloc删除并返回自由列表中的第一个元素。

发表评论:

控制面板
您好,欢迎到访网站!
  查看权限
网站分类
最新留言
    友情链接