Linux内存管理中的术语、变量和小函数

最近学了点内存管理基本概念,仅以此文做个记录。

术语

PGD, PUD, PMD, PTE

PGD: Page Global Directory
PUD: Page Upper Directory
PMD: Page Middle-level Directory
PTE: Page Table Entry

这么看其实非常枯燥,请看下文中pgd_index, pud_index这小节。

变量/宏

__START_KERNEL_map,内核虚拟地址的起始地址

定义很简单,但这就是内核虚拟地址的启示位子。

#define __START_KERNEL_map  _AC(0xffffffff80000000, UL)

好,我们来看看为什么。

先看链接脚本: arch/x86/kernel/vmlinux.lds.S

#define __START_KERNEL_map  _AC(0xffffffff80000000, UL)

#define __START_KERNEL      (__START_KERNEL_map + __PHYSICAL_START)


SECTIONS
{

    . = __START_KERNEL;
    phys_startup_64 = ABSOLUTE(startup_64 - LOAD_OFFSET);

    /* Text and read-only data */
    .text :  AT(ADDR(.text) - LOAD_OFFSET) {
        _text = .;

这里只看x86_64的。可以看到 .text, _text的虚拟地址就是__START_KERNEL,如果__PHYSICAL_START默认为0x1000000, 那么 这个 地址 就是
__START_KERNEL_map + 0x1000000
= 0xffffffff81000000。

ok,那怎么证明呢? 有几个证据。

证明一, readelf

第一个就是看elf的program header。

readelf -l vmlinux

Elf file type is EXEC (Executable file)
Entry point 0x1000000
There are 5 program headers, starting at offset 64

Program Headers:
  Type           Offset             VirtAddr           PhysAddr
                 FileSiz            MemSiz              Flags  Align
  LOAD           0x0000000000200000 0xffffffff81000000 0x0000000001000000
                 0x0000000000da0000 0x0000000000da0000  R E    200000
  LOAD           0x0000000001000000 0xffffffff81e00000 0x0000000001e00000
                 0x0000000000143000 0x0000000000143000  RW     200000
  LOAD           0x0000000001200000 0x0000000000000000 0x0000000001f43000
                 0x0000000000019018 0x0000000000019018  RW     200000
  LOAD           0x000000000135d000 0xffffffff81f5d000 0x0000000001f5d000
                 0x000000000016c000 0x00000000002ef000  RWE    200000
  NOTE           0x0000000000a38e08 0xffffffff81838e08 0x0000000001838e08
                 0x0000000000000204 0x0000000000000204         4

看第一个program header的虚拟地址是0xffffffff81000000, 是不是就是它了呢。

证明二,打印符号 _text

第二个证明,干脆在内核中打印_text这个符号的地址呗。

恩,请自行打印,就不在这里写了。

证明三, 计算 level2_kernel_pgt的index

第三个证明, 查看页表。

head_64.S设置的页表 尝试打印页表 中, 我们可以看到 level2_kernel_pgt 是 从 pgd[511] 和 pud[510] 指过来的。 好了, 那我们分析一下 __START_KERNEL_map。

  __START_KERNEL_map
= 0x ffff       ffff                 8000             0000
= 0x ffff       ffff                 8            000 0000
= 0x ffff  (1111 1111     1111 1111 1000)b        000 0000
= 0x ffff  (1111 11111)b  (111 1111 10)b  (00)b   000 0000
= 0x ffff   511            510            (00)b   000 0000

写得有点丑,大家将就看一下。低48bit中的高9位是pgd的index,接下来的9位是pud的index。上面把这两个域截出来了,正好是 511 和 510。完美~

__PAGE_OFFSET,整个虚拟地址的起始地址

恩,这个是我猜的,暂时还不确认哈

/*
 * Set __PAGE_OFFSET to the most negative possible address +
 * PGDIR_SIZE*16 (pgd slot 272).  The gap is to allow a space for a
 * hypervisor to fit.  Choosing 16 slots here is arbitrary, but it's
 * what Xen requires.
 */
#define __PAGE_OFFSET           _AC(0xffff880000000000, UL)

这高级玩意还真有点难懂,理解要是不对,欢迎大家拍砖。

  0x ffff 0000 0000 0000       A
  0x 0000 8000 0000 0000       B
+ 0x 0000 0800 0000 0000       C
= 0x ffff 8800 0000 0000       __PAGE_OFFSET

A 是 现在页表支持最大的内存空间。因为现在我看,一个页表最多也就能表示48位的地址空间了。(init_level4_pgt就是这种页表。)

B 是 most nagetive possible address。 这个想了一会儿发现还真的是的。这个使用补码表示,最高位留作符号位。最高位取1, 其余为0时,就是这么多位能表示的最小的负数。

C 是 注释中说的那个16个PGDIR_SIZE。 因为 (C >> 39) = 16。

看到这里有点没有想明白,为啥这个地址还是个有符号数呢?

小函数

pgd_index(), pud_index(), pmd_index()

这几个函数或者宏是用来遍历页表的

/*
 * the pgd page can be thought of an array like this: pgd_t[PTRS_PER_PGD]
 *
 * this macro returns the index of the entry in the pgd page which would
 * control the given virtual address
 */
#define pgd_index(address) (((address) >> PGDIR_SHIFT) & (PTRS_PER_PGD - 1))

/* to find an entry in a page-table-directory. */
static inline unsigned long pud_index(unsigned long a
  • 1
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值