http://www.lslnet.com/linux/dosc1/38/linux-277424.htm


linux内核用的页目录表、页表位置及MITOCW问题等

请问一下Linux内核的页目录表和页表在什么位置?
我知道cr3是指向页表的,这个位置是用类似alloc函数分配的吗?
还有页表的位置是固定的吗?还是也是分配的?这些东西我最好去看内核的那个文件?
另外我最近在做MITOCW的OS(graduate,6.828)的6个实验,举步维艰,也不知道做出来的对不对(虽然通过了它的评分脚本,但有的我感 觉总是自己做的不对)。有没有大侠指点指点。


Re: linux内核用的页目录表、页表位置及MITOCW问题等

内核空间使用的页目录是固定的。分析如下:
1. 在arch/i386/kernel/head.S中定义了
.org 0x1000
ENTRY(swapper_pg_dir)
.long 0x00102007
.long 0x00103007
.fill BOOT_USER_PGD_PTRS-2,4,0
/* default: 766 entries */
.long 0x00102007
.long 0x00103007
/* default: 254 entries */
.fill BOOT_KERNEL_PGD_PTRS-2,4,0
即从swapper_pg_dir开始,定义了1024个页目录项。几个常数的定义在include/asm-i386/pgtable.h中:
extern pgd_t swapper_pg_dir[1024];
#define TWOLEVEL_PGDIR_SHIFT 22
#define BOOT_USER_PGD_PTRS (__PAGE_OFFSET >> TWOLEVEL_PGDIR_SHIFT)
#define BOOT_KERNEL_PGD_PTRS (1024-BOOT_USER_PGD_PTRS)
,BOOT_KERNEL_PGD_PTRS为256,BOOT_USER_PGD_PTRS为768。
一个页面目录的大小为4KB,共有1024个目录项,每个目录项指示一个4KB大小的页表,一个4KB大小的页表有1024项页表项,每个页表项 映射4KB大小的物理页框,所以这里共映射了4KB × 1024 ×1024=4GB的空间。该空间又分为两部分,页目录中的低768个页目录项映射了用户空间3GB,高256个页目录项映射了内核空间1GB。

2.内核虚存空间的控制结构为全局变量init_mm,初始化于setup_arch函数:
init_mm.start_code = (unsigned long) &_text;
init_mm.end_code = (unsigned long) &_etext;
init_mm.end_data = (unsigned long) &_edata;
init_mm.brk = (unsigned long) &_end;


3.对内核空间页目录和页表的初始化在setup_arch函数中调用paging_init函数完成。paging_init函数又进一步调用 pagetable_init完成。这两个函数定义于arch/i386/mm/init.c


4. paging_init调用pagetable_init完成对页目录、页表的初始化后,立即调用了load_cr3(swapper_pg_dir), 这是一个宏,定义于include/asm-i386/processor.h,
#define load_cr3(pgdir) \
asm volatile("movl %0,%%cr3": :"r" (__pa(pgdir)));
其作用就是把页目录的物理基地址装入CR3寄存器。

5. pagetable_init只初始化了内核空间的映射。诸进程共享内核空间。也就是说,各个进程的最后1G的映射是一样的。在创建进程时,会把后256 个页目录拷贝到进程的页目录中。具体调用为do_fork->copy_mm->mm_init,这些函数都定义在 kernel/fork.c中。在mm_init中,执行:

mm->pgd = pgd_alloc(mm);
pgd_alloc定义于arch/i386/mm/pgtable.c中:
pgd_t *pgd_alloc(struct mm_struct *mm)
{
pgd_t *pgd = (pgd_t *)__get_free_page(GFP_KERNEL);

if (pgd) {
memset(pgd, 0, USER_PTRS_PER_PGD * sizeof(pgd_t));
memcpy(pgd + USER_PTRS_PER_PGD,
swapper_pg_dir + USER_PTRS_PER_PGD,
(PTRS_PER_PGD - USER_PTRS_PER_PGD) * sizeof(pgd_t));
}
return pgd;
}
其中memcpy调用实现了自swapper_pg_dir开始的最后256个页目录项的拷贝。


Re: linux内核用的页目录表、页表位置及MITOCW问题等

First of all, try to forget Linux details.

Think of things like this: For IA32 CPUs, three addresses:
----------------------------
Logical Address; Linear Address; Physical Address.
----------------------------

1. After compilation and linkage, you could find the "Logical Address" if you read the map file. Please refer to gcc manual for how to get a map file for your elf image. Usually, we say: Logical Addess = Segment Selector + Offset. When under "Flat Address" Modelwith protected mode, the offset part is simply the Logical Address then. Also, note that, for most of OS, for example, Linux, usually run IA32 with Flat Model with Paging Enabled. So, simple forget the Segmentation model.


Ok, now, the CPU get the binary loaded up. Its Instruction Fetch Unit starts to execute instructions or your codes. The address the cpu core got is the Logical Address.

Then with protected mode, CPU logic will have to figure out where the physical address is.


2. With protected mode, all CS, DS...registers become "Segment Selector". For code, CS is used. For data, for example, DS is used. With the value of CS, we find the Index of the GDT array. In other words,
we find an entry in the GDT array, which is pointed out by a well-know register GDTR. What we calle the entry? Segment Descriptor! What contents inside this Segment Descriptor? Besdies other info, one of them is the: Segment Base Address, with which, CPU can figure out the Linear Address, which is composed of "segment address" + "offset".

3.If Paging is NOT enabled, then Linear Address is equal to the physical address. CPU will then go there to fetch either instruction or data.


4. If Paging is enabled, then Linear Address is logically*** partitioned to Three Level Directory --Dir, Table and Offset. Linux actually only do the two level page tables. The CR3 is used for providing the base address of Page Table Dir. In other words, the base address CR3 holds MUST BE THE PHYSICAL ADDRESS. With the CR3's help, CPU finally can figure out and get a logical address's physical address and then cpu can starts to load/store.....from system bus.

If you happen to know MIPS or PowerPC, they all have similar stuff......






Re: linux内核用的页目录表、页表位置及MITOCW问题等

BNN's explanation is more essential than mine.
It is emphasized how to interact between architecture of processor and the OS software.The latter must obey the former's rules such as data structures and the timing sequence.Memory management is just one aspect of these interactions, which should be the focuses of our attention.


Re: linux内核用的页目录表、页表位置及MITOCW问题等

Thank you very much, but i think maybe you misunderstanding me. What i want to know is the physical address(or kernel liner address?) of the page directory tables and the page tables. I know
cr3 directs the PDT, and every PDE directs a PT. My question is, are the content of PDEs fixed? or
in most version of Linux(IA32), They are fixed?
3ks.


Re: linux内核用的页目录表、页表位置及MITOCW问题等

The contents of kernel space's PDEs (256 entries) are fixed. My first word of my first answer is very clear.


Re: linux内核用的页目录表、页表位置及MITOCW问题等

Any more, the physical address of Page Directory Table and Page Table of kernel is fixed too. As far as a process is concerned, the space of its PD table is temporarily allocated by __get_free_page function and so their physical addresses are unconstant, but their physical addresses can be known by using macro __pa .

Once more, the last 1GB's PDEs of a process's space are all copied from the kernel's Page Directory Table's aftermost 256 entries, so thire contents are fixed for any process.

You'd better read my first answer carefully again.



Re: linux内核用的页目录表、页表位置及MITOCW问题等

Thank you for your advices. Maybe I've got it.


Reply via email to