xv6(6)
xv6运行第一个程序的过程:
int main(void) { kinit1(end, P2V(4*1024*1024)); // phys page allocator kvmalloc(); // kernel page table mpinit(); // collect info about this machine lapicinit(); seginit(); // set up segments cprintf("\ncpu%d: starting xv6\n\n", cpu->id); picinit(); // interrupt controller ioapicinit(); // another interrupt controller consoleinit(); // I/O devices & their interrupts uartinit(); // serial port pinit(); // process table tvinit(); // trap vectors binit(); // buffer cache fileinit(); // file table iinit(); // inode cache ideinit(); // disk if(!ismp) timerinit(); // uniprocessor timer startothers(); // start other processors kinit2(P2V(4*1024*1024), P2V(PHYSTOP)); // must come after startothers() userinit(); // first user process // Finish setting up this processor in mpmain. mpmain(); }
后面倒数的两个函数是关键:
void userinit(void) //初始化proc的部分成员 { struct proc *p; extern char _binary_initcode_start[], _binary_initcode_size[]; p = allocproc(); // 初始化kstack、tf等成员(初始化为申请的空间) trapret forkret initproc = p; if((p->pgdir = setupkvm()) == 0) // 初始化pgdir成员 panic("userinit: out of memory?"); inituvm(p->pgdir, _binary_initcode_start, (int)_binary_initcode_size); p->sz = PGSIZE; memset(p->tf, 0, sizeof(*p->tf)); // tf的成员初始化 p->tf->cs = (SEG_UCODE << 3) | DPL_USER; p->tf->ds = (SEG_UDATA << 3) | DPL_USER; p->tf->es = p->tf->ds; p->tf->ss = p->tf->ds; p->tf->eflags = FL_IF; p->tf->esp = PGSIZE; // 0x1000 p->tf->eip = 0; // beginning of initcode.S safestrcpy(p->name, "initcode", sizeof(p->name)); p->cwd = namei("/"); p->state = RUNNABLE; }
static void mpmain(void) //初始化idt 调用scheduler { cprintf("cpu%d: starting\n", cpu->id); idtinit(); // load idt register xchg(&cpu->started, 1); // tell startothers() we're up scheduler(); // start running processes }
// proc.c void scheduler(void) { struct proc *p; for(;;){ // Enable interrupts on this processor. sti(); // Loop over process table looking for process to run. acquire(&ptable.lock); for(p = ptable.proc; p < &ptable.proc[NPROC]; p++){ if(p->state != RUNNABLE) continue; // Switch to chosen process. It is the process's job // to release ptable.lock and then reacquire it // before jumping back to us. proc = p; switchuvm(p); p->state = RUNNING; swtch(&cpu->scheduler, proc->context); //从这里开始 switchkvm(); // Process is done running for now. // It should have changed its p->state before coming back. proc = 0; } release(&ptable.lock); } }
# swtch.S .globl swtch swtch: movl 4(%esp), %eax # &cpu->scheduler movl 8(%esp), %edx # proc->context # Save old callee-save registers pushl %ebp pushl %ebx pushl %esi pushl %edi # Switch stacks movl %esp, (%eax) # eip --> [eax] movl %edx, %esp # 切换栈 # Load new callee-save registers popl %edi popl %esi popl %ebx popl %ebp ret # 弹出context->eip 即forkret
//proc.c void forkret(void) #第一次在这里下断 { static int first = 1; // Still holding ptable.lock from scheduler. release(&ptable.lock); if (first) { // Some initialization functions must be run in the context // of a regular process (e.g., they call sleep), and thus cannot // be run from main(). first = 0; initlog(); } // Return to "caller", actually trapret (see allocproc). }
.globl trapret trapret: popal popl %gs popl %fs popl %es popl %ds addl $0x8, %esp # trapno and errcode iret # r0 --> r3 5个参数出栈
# initcode.S # exec(init, argv) .globl start start: # r3 注意此时的栈内容 pushl $argv pushl $init pushl $0 // where caller pc would be movl $SYS_exec, %eax int $T_SYSCALL # 进入系统调用 # for(;;) exit(); exit: movl $SYS_exit, %eax int $T_SYSCALL jmp exit # char init[] = "/init\0"; init: .string "/init\0" # char *argv[] = { init, 0 }; .p2align 2 argv: .long init .long 0
# vectors.S通过vectors.pl产生,编译才有 # generated by vectors.pl - do not edit # handlers .globl alltraps .globl vector0 # r0 注意此时的栈内容 脑中想象一下 vector0: pushl $0 pushl $0 jmp alltraps .globl vector1 vector1: pushl $0 pushl $1 jmp alltraps .globl vector2 vector2: pushl $0 pushl $2 jmp alltraps .globl vector3 vector3: pushl $0 pushl $3 jmp alltraps .globl vector4 vector4: pushl $0 pushl $4 jmp alltraps .globl vector5 vector5: pushl $0 pushl $5 jmp alltraps ... # vector table .data .globl vectors vectors: .long vector0 .long vector1 .long vector2 .long vector3 .long vector4 .long vector5 ...

浙公网安备 33010602011771号