# xv6 Kernel-3: Startup + Organization ### xv6 開機的三大步驟 1. `entry.S`: set up stack 1. `start.c`: machine mode 1. `main.c`: supervisor mode * modes of xv6 1. machine mode: 極少的 kernel 會使用 machine mode 1. supervisor mode: 多數 kernel 都是使用這個 mode 1. user mode: user program 使用的 mode ### `entry.S` 的解析 ```asm= # qemu -kernel loads the kernel at 0x80000000 # and causes each hart (i.e. CPU) to jump there. # kernel.ld causes the following code to # be placed at 0x80000000. .section .text .global _entry _entry: # set up a stack for C. # stack0 is declared in start.c, # with a 4096-byte stack per CPU. # sp = stack0 + (hartid * 4096) la sp, stack0 li a0, 1024*4 csrr a1, mhartid addi a1, a1, 1 mul a0, a0, a1 add sp, sp, a0 # jump to start() in start.c call start spin: j spin ``` * [csr](https://ithelp.ithome.com.tw/articles/10289643) ### `main.c` 的解析 ```clike= #include "types.h" #include "param.h" #include "memlayout.h" #include "riscv.h" #include "defs.h" volatile static int started = 0; // start() jumps here in supervisor mode on all CPUs. void main() { if(cpuid() == 0){ consoleinit(); printfinit(); printf("\n"); printf("xv6 kernel is booting\n"); printf("\n"); kinit(); // physical page allocator kvminit(); // create kernel page table kvminithart(); // turn on paging procinit(); // process table trapinit(); // trap vectors trapinithart(); // install kernel trap vector plicinit(); // set up interrupt controller plicinithart(); // ask PLIC for device interrupts binit(); // buffer cache iinit(); // inode table fileinit(); // file table virtio_disk_init(); // emulated hard disk userinit(); // first user process __sync_synchronize(); started = 1; } else { while(started == 0) ; __sync_synchronize(); printf("hart %d starting\n", cpuid()); kvminithart(); // turn on paging trapinithart(); // install kernel trap vector plicinithart(); // ask PLIC for device interrupts } scheduler(); } ``` 當 xv6 開機時,只有其中一個 CPU 在做初始化了動作,其他的 CPU 就要等到這個 CPU 把事情做完之後,才會開始做各自的事情。 * 在 `main()` 的最後,會執行 `scheduler()` (可能跟 yunikoen 的 scheduler 的角色有點像) ### `kernel/proc.c: scheduler()` * 這是在 `main()` 最後一行執行的 function ```clike= void scheduler(void) { struct proc *p; struct cpu *c = mycpu(); c->proc = 0; for(;;){ // Avoid deadlock by ensuring that devices can interrupt. intr_on(); for(p = proc; p < &proc[NPROC]; p++) { acquire(&p->lock); if(p->state == RUNNABLE) { // Switch to chosen process. It is the process's job // to release its lock and then reacquire it // before jumping back to us. p->state = RUNNING; c->proc = p; swtch(&c->context, &p->context); // Process is done running for now. // It should have changed its p->state before coming back. c->proc = 0; } release(&p->lock); } } } ``` * `scheduler()` 是只有一個 thread 在執行嗎? ### 註記 * `__sync_syncronize()` 的作用: * 必須要先前的程式都執行完了,才可以往下執行 * `kernel/param.h` 裏面有紀錄了一些參數 ## 參考資料 * [xv6 Kernel-3: Startup + Organization](https://www.youtube.com/watch?v=6hhJ6JN95As&list=PLbtzT1TYeoMhTPzyTZboW_j7TPAnjv9XB&index=4)
×
Sign in
Email
Password
Forgot password
or
Sign in via Google
Sign in via Facebook
Sign in via X(Twitter)
Sign in via GitHub
Sign in via Dropbox
Sign in with Wallet
Wallet (
)
Connect another wallet
Continue with a different method
New to HackMD?
Sign up
By signing in, you agree to our
terms of service
.