进程管理 - 常见错误

错误 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;
    }
}