內核源碼下載:
https://mirrors.edge.kernel.org/pub/linux/kernel/
http://ftp.sjtu.edu.cn/sites/ftp.kernel.org/pub/linux/kernel/
本書基於2.4.16版本
分段分頁
分段。Linux在啓動過程中設置了段寄存器的值和全局描述符表GDT的內容。
段選擇子:
// FILE: include/asm-i386/segment.h
#define __KERNEL_CS 0x10 // 內核代碼段, index=2 TI=0 RPL=0
#define __KERNEL_DS 0x18 // 內核數據段, index=3 TI=0 RPL=0
#define __USER_CS 0x23 // 用戶代碼段, index=4 TI=0 RPL=3
#define __USER_DS 0x2B // 用戶數據段, index=5 TI=0 RPL=3
段描述符GDT:
1)段基址都爲0x0000_0000;2)段界限都爲0xffff; 3)粒度G都爲1,即段長單位爲4KB;
4)段的D位爲1,即對這4個段的訪問都爲32位指令;5)段的P位爲1,即4個段都在內存。
// FILE: arch/i386/kernel/head.S
ENTRY(gdt_table)
.quad 0x0000000000000000 /* NULL descriptor */
.quad 0x0000000000000000 /* not used */
.quad 0x00cf9a000000ffff /* 0x10 kernel 4GB code at 0x00000000 */
.quad 0x00cf92000000ffff /* 0x18 kernel 4GB data at 0x00000000 */
.quad 0x00cffa000000ffff /* 0x23 user 4GB code at 0x00000000 */
.quad 0x00cff2000000ffff /* 0x2b user 4GB data at 0x00000000 */
.quad 0x0000000000000000 /* not used */
.quad 0x0000000000000000 /* not used */
分頁。
Linux沒有把這幾個類型直接定義長整數而是定義爲一個結構,是爲了讓gcc在編譯時進行更嚴格的類型檢查。另外,還定義了幾個宏來訪問這些結構的成分。
// FILE: include/asm-i386/page.h
// These are used to make use of C type-checking..
typedef struct { unsigned long pte_low; } pte_t;
typedef struct { unsigned long pmd; } pmd_t;
typedef struct { unsigned long pgd; } pgd_t;
typedef struct { unsigned long pgprot; } pgprot_t;
#define pte_val(x) ((x).pte_low)
#define pmd_val(x) ((x).pmd)
#define pgd_val(x) ((x).pgd)
#define pgprot_val(x) ((x).pgprot)
頁表項。把標誌位定義爲宏,而不是位段,更有利於編碼。
// FILE: include/asm-i386/pgtable.h
#define _PAGE_PRESENT 0x001
#define _PAGE_RW 0x002
#define _PAGE_USER 0x004
#define _PAGE_PWT 0x008
#define _PAGE_PCD 0x010
#define _PAGE_ACCESSED 0x020
#define _PAGE_DIRTY 0x040
#define _PAGE_PSE 0x080 /* 4 MB (or 2MB) page, Pentium+, if present.. */
#define _PAGE_GLOBAL 0x100 /* Global TLB entry PPro+ */
extern pgd_t swapper_pg_dir[1024]; // 頁目錄表
/* page table for 0-4MB for everybody */
extern unsigned long pg0[1024]; // 一個臨時頁表
中斷機制
Intel x86通過兩片級聯的中斷控制器8259A來響應15個外中斷源,每個8259A可管理8箇中斷源。
IRQ0 時鐘;IRQ1 鍵盤
初始化中斷控制器8259A
// FILE: arch/i386/kernel/i8259.c
void __init init_8259A(int auto_eoi)()
{
...
}
75