xv6_chapter7 Scheduling
graph TD A[用户进程运行] --> B{时间片到期/系统调用/中断} B --> C[进入内核态 usertrap] C --> D[保存用户寄存器到trapframe] D --> E{需要切换进程?} E -->|是| F[调用yield函数] E -->|否| G[处理完毕返回用户态] F --> H[获取进程锁 p->lock] H --> I[设置进程状态为RUNNABLE] I --> J[调用sched函数] J --> K[检查锁状态和中断状态] K --> L[保存中断状态] L --> M[调用swtch函数进行上下文切换] M --> N[保存当前进程的callee-saved寄存器到p->context] N --> O[恢复调度器的callee-saved寄存器从cpu->context] O --> P[返回到scheduler函数] P --> Q[scheduler循环查找RUNNABLE进程] Q --> R{找到可运行进程?} R -->|否| Q R -->|是| S[设置进程状态为RUNNING] S --> T[再次调用swtch函数] T --> U[保存调度器寄存器到cpu->context] U --> V[恢复新进程寄存器从p->context] V --> W[返回到新进程的内核栈] W --> X[释放进程锁] X --> Y[恢复中断状态] Y --> Z[返回到usertrapret] Z --> AA[恢复用户寄存器从trapframe] AA --> BB[切换到用户页表] BB --> CC[返回用户态继续执行] G --> AA style A fill:#e1f5fe style CC fill:#e8f5e8 style M fill:#fff3e0 style T fill:#fff3e0 style P fill:#f3e5f5 style Q fill:#f3e5f5 重要的数据结构: // 保存内核上下文切换时的寄存器 struct context { uint64 ra; // 返回地址 uint64 sp; // 栈指针 // callee-saved 寄存器 s0-s11 uint64 s0, s1, s2, s3, s4, s5, s6, s7, s8, s9, s10, s11; }; // 每个进程的状态 struct proc { struct spinlock lock; enum procstate state; // 进程状态 struct context context; // 上下文切换时保存的寄存器 struct trapframe *trapframe; // 用户态寄存器保存区 // ....