1.啓動部分: bootasm.S bootmain.c 和xv6初始化模塊:main.chtml
# Start the first CPU: switch to 32-bit protected mode, jump into C. # The BIOS loads this code from the first sector of the hard disk into # memory at physical address 0x7c00 and starts executing in real mode # with %cs=0 %ip=7c00. .code16 # Assemble for 16-bit mode .globl start start: cli # BIOS enabled interrupts; disable # Zero data segment registers DS, ES, and SS. xorw %ax,%ax # Set %ax to zero movw %ax,%ds # -> Data Segment movw %ax,%es # -> Extra Segment movw %ax,%ss # -> Stack Segment
2.中斷與系統調用部分: trap.c trapasm.S vectors.S & vectors.pl syscall.c sysproc.c proc.c 以及相關其餘文件代碼git
// syscall.h System call numbers …… #define SYS_fork 1 #define SYS_exit 2 #define SYS_wait 3 #define SYS_pipe 4 #define SYS_read 5 #define SYS_kill 6 #define SYS_exec 7 …… // syscall.c 聲明系統調用 …… extern int sys_chdir(void); extern int sys_close(void); extern int sys_dup(void); extern int sys_exec(void); extern int sys_exit(void); extern int sys_fork(void); extern int sys_fstat(void); extern int sys_getpid(void); extern int sys_kill(void); extern int sys_link(void); extern int sys_mkdir(void); extern int sys_mknod(void); extern int sys_open(void); …… // sysproc.c 定義前面聲明的系統調用接口 int sys_fork(void) { return fork(); } int sys_exit(void) { exit(); return 0; // not reached } int sys_wait(void) { return wait(); } int sys_kill(void) { int pid; if(argint(0, &pid) < 0) return -1; return kill(pid); } ……
3.什麼是用戶態和內核態,二者有何區別? 什麼是中斷和系統調用,二者有何區別? 計算機在運行時,是如何肯定當前處於用戶態仍是內核態的?編程
4.計算機開始運行階段就有中斷嗎? XV6 的中斷管理是如何初始化的? XV6 是如何實現內核態到用戶態的轉變的? XV6 中的硬件中斷是如何開關的? 實際的計算機裏,中斷有哪幾種?api
5.什麼是中斷描述符,中斷描述符表(IDT)? 在XV6裏是用什麼數據結構表示的?安全
// trap.c # generated by vectors.pl - do not edit # handlers .globl alltraps .globl vector0 vector0: pushl $0 pushl $0 jmp alltraps .globl vector1 vector1: pushl $0 pushl $1 jmp alltraps .globl vector2 ……
// trapasm.S # vectors.S sends all traps here. .globl alltraps alltraps: # Build trap frame. pushl %ds pushl %es pushl %fs pushl %gs pushal # Set up data and per-cpu segments. 設置數據和CPU段 movw $(SEG_KDATA<<3), %ax movw %ax, %ds movw %ax, %es movw $(SEG_KCPU<<3), %ax movw %ax, %fs movw %ax, %gs # Call trap(tf), where tf=%esp 壓入 %esp pushl %esp # 調用trap call trap addl $4, %esp
// trap.c //PAGEBREAK: 41 void trap(struct trapframe *tf) { if(tf->trapno == T_SYSCALL){ // 判斷該中斷是否爲系統調用 if(proc->killed) exit(); proc->tf = tf; syscall(); if(proc->killed) exit(); return; } switch(tf->trapno){ …… // PAGEBREAK: 13 // tf->trapno與其餘case語句對不上,除零被視爲代碼錯誤中斷,進入這裏殺掉進程 default: if(proc == 0 || (tf->cs&3) == 0){ // In kernel, it must be our mistake. cprintf("unexpected trap %d from cpu %d eip %x (cr2=0x%x)\n", tf->trapno, cpu->id, tf->eip, rcr2()); panic("trap"); } // In user space, assume process misbehaved. cprintf("pid %d %s: trap %d err %d on cpu %d " "eip 0x%x addr 0x%x--kill proc\n", proc->pid, proc->name, tf->trapno, tf->err, cpu->id, tf->eip, rcr2()); proc->killed = 1; } …… }
// trap.c // Interrupt descriptor table (shared by all CPUs). struct gatedesc idt[256]; extern uint vectors[]; // in vectors.S: array of 256 entry pointers …… // x86.h //PAGEBREAK: 36 // Layout of the trap frame built on the stack by the // hardware and by trapasm.S, and passed to trap(). struct trapframe { // registers as pushed by pusha uint edi; uint esi; uint ebp; uint oesp; // useless & ignored uint ebx; uint edx; uint ecx; uint eax; …… }; // vector.S 0~255共256個 vectors: .long vector0 .long vector1 .long vector2 .long vector3 .long vector4 .long vector5 .long vector6 .long vector7 .long vector8 .long vector9 ……
6.請以系統調用setrlimit(該系統調用的做用是設置資源使用限制)爲例,敘述如何在XV6中實現一個系統調用。(提示:須要添加系統調用號,系統調用函數,用戶接口等等)。bash
// syscall.h …… #define SYS_mkdir 20 #define SYS_close 21 #define SYS_setrlimit 22 // add by yangyu
// syscall.c …… static int (*syscalls[])(void) = { …… [SYS_mkdir] sys_mkdir, [SYS_close] sys_close, [SYS_setrlimit] SYS_setrlimit, // add by yangyu };
// syspro.c …… int sys_uptime(void) { uint xticks; acquire(&tickslock); xticks = ticks; release(&tickslock); return xticks; } // 在這裏面寫邏輯,限制進程資源的使用 int sys_setrlimit(void) { // to do }
// syspro.c …… // system calls int fork(void); int exit(void) __attribute__((noreturn)); …… // 調用該接口陷入內核執行系統調用 int setrlimit(int resource, const struct rlimit *rlim);
// usys.S …… SYSCALL(sleep) SYSCALL(uptime) SYSCALL(setrlimit) // add by yangyu
[1] xv6 idt初始化
[2] xv6中文文檔
[3] xv6 alltraps
[4] [xv6 trap/interrupt](網絡