进程管理 - 常见错误
错误 1:栈初始化不正确
症状
进程创建后第一次调度就崩溃。
原因
栈上的初始上下文布局必须与上下文切换代码的期望匹配。
解决方案
确保栈布局与switch_context中pop的顺序一致:
uint32_t *sp = (uint32_t *)proc->kernel_stack;
*(--sp) = (uint32_t)entry; // EIP (ret弹出)
*(--sp) = 0; // EBP (pop ebp)
*(--sp) = 0; // EBX (pop ebx)
*(--sp) = 0; // ESI (pop esi)
*(--sp) = 0; // EDI (pop edi)
proc->esp = (uint32_t)sp;错误 2:内核栈溢出
症状
进程运行一段时间后随机崩溃,或修改了其他进程的数据。
原因
内核栈大小不足(如只分配了1KB)。
解决方案
为每个进程分配至少4KB的内核栈,复杂系统中可能需要8KB:
#define KERNEL_STACK_SIZE 4096
uint32_t stack = (uint32_t)kmalloc_aligned(KERNEL_STACK_SIZE);
proc->kernel_stack = stack + KERNEL_STACK_SIZE; // 栈顶错误 3:PID分配冲突
症状
两个不同进程有相同的PID。
原因
PID计数器没有正确递增,或在创建进程时有竞态条件。
解决方案
在单核环境中确保PID分配在关中断状态下进行:
static uint32_t next_pid = 1;
// 在process_create中:
proc->pid = next_pid++; // 原子递增错误 4:忘记初始化PCB字段
症状
进程行为不可预测。
原因
kmalloc返回的内存包含垃圾数据。
解决方案
始终使用memset清零:
process_t *proc = kmalloc(sizeof(process_t));
memset(proc, 0, sizeof(process_t)); // 关键!错误 5:从进程链表中删除时的指针错误
症状
遍历进程列表时崩溃或无限循环。
原因
删除链表节点时没有正确维护前驱指针。
解决方案
void process_remove(process_t *proc) {
if (proc_list == proc) {
proc_list = proc->next;
return;
}
process_t *prev = proc_list;
while (prev && prev->next != proc) {
prev = prev->next;
}
if (prev) {
prev->next = proc->next;
}
}