+ // 为内核创建一个专属栈空间。
+ for (size_t i = 0; i < (KSTACK_SIZE >> PG_SIZE_BITS); i++) {
+ vmm_alloc_page(KERNEL_PID, (void*)(KSTACK_START + (i << PG_SIZE_BITS)), NULL, PG_PREM_RW, 0);
+ }
+ kprintf(KINFO "[MM] Allocated %d pages for stack start at %p\n", KSTACK_SIZE>>PG_SIZE_BITS, KSTACK_START);
+
+ sched_init();
+
+ spawn_lxinit();
+}
+
+/**
+ * @brief 创建并运行init进程
+ *
+ */
+void spawn_lxinit() {
+ struct proc_info kinit;
+ uint32_t* kstack = (uint32_t*)KSTACK_TOP - 4 * 5;
+
+ memset(&kinit, 0, sizeof(kinit));
+ kinit.page_table = (void*) cpu_rcr3();
+ kinit.parent = -1;
+ kinit.pid = 1;
+ kinit.intr_ctx = (isr_param) {
+ .registers.esp = kstack,
+ .cs = KCODE_SEG,
+ .eip = (void*)_kernel_post_init,
+ .ss = KDATA_SEG,
+ .eflags = cpu_reflags()
+ };
+
+ /*
+ 因为schedule从设计上是需要在中断环境中执行的
+ 可是我们需要在这里手动调用 schedule,从而使我们的init能够被执行。
+ 所以需要模拟中断产生时的栈里内容。
+ */
+ kstack[2] = kinit.intr_ctx.eip;
+ kstack[3] = kinit.intr_ctx.cs;
+ kstack[4] = kinit.intr_ctx.eflags;
+
+ push_process(&kinit);
+
+ schedule();