Skip to content

进程管理 API

本文档介绍 NoobKernel 进程管理模块的主要 API。

CPU 管理

#include <task/proc.h>

// 初始化 CPU
void init_cpu(u64 id);

// 获取当前 CPU 结构
struct cpu *thiscpu(void);

示例

// 获取当前 CPU
struct cpu *c = thiscpu();
infof("Current process: %s", c->proc ? c->proc->comm : "idle");

进程分配

#include <task/proc.h>

// 分配进程结构
struct proc *alloc_proc(void);

// 释放进程结构
void free_proc(struct proc *p);

// 分配 PID
pid_t alloc_pid(void);

示例

struct proc *p = alloc_proc();
if (!p) {
    return -ENOMEM;
}

infof("Created process pid=%d", p->pid);

// 释放进程
free_proc(p);

进程状态

#define PROC_UNUSED    0
#define PROC_IDLE      1
#define PROC_RUNNABLE  2
#define PROC_RUNNING   3
#define PROC_SLEEPING  4
#define PROC_ZOMBIE    5

调度器

#include <task/sched.h>

// 初始化运行队列
void init_runq(void);

// 加入运行队列
void enqueue_proc(int hartid, struct proc *p);

// 从运行队列取出
struct proc *dequeue_proc(int hartid);

// 让出 CPU
void sched_yield(void);

// 检查运行队列是否空
bool is_runq_empty(int hartid);

示例

// 让出 CPU
sched_yield();

// 检查运行队列
if (is_runq_empty(0)) {
    infof("No processes to run");
}

上下文切换

// 切换上下文
void context_switch(struct context *old, struct context *new);

// 切换到指定上下文
void context_switch_to(struct context *new);

内核线程

#include <task/kthread.h>

// 创建内核线程
struct proc *kthread_create(void (*func)(void *), void *arg);

// 退出内核线程
void kthread_exit(void);

示例

void my_thread(void *arg) {
    infof("Thread started");
    while (1) {
        // 执行任务
        ...
        sched_yield();
    }
}

// 创建线程
struct proc *thread = kthread_create(my_thread, NULL);
if (!thread) {
    return -ENOMEM;
}

// 加入运行队列
enqueue_proc(0, thread);

进程结构

struct proc {
    char comm[16];           // 进程名
    pid_t pid;               // 进程 ID
    pid_t tgid;              // 线程组 ID

    pagetable_t pagetable;   // 页表
    struct list_head vma;    // VMA 链表

    struct context ctx;      // 上下文
    struct ktrapframe ktf;   // 内核 trapframe
    void *kstack;            // 内核栈

    int state;               // 状态
    struct list_head runq;   // 运行队列节点

    struct proc *parent;     // 父进程
    struct list_head children;  // 子进程
    struct list_head sibling;   // 兄弟进程

    struct fd_table *fd_table;  // 文件描述符表
    struct dentry *pwd;         // 工作目录

    spinlock_t lock;         // 进程锁
};

进程操作

// 获取进程锁
spinlock_acquire(&p->lock);

// 修改进程状态
p->state = PROC_SLEEPING;

// 释放进程锁
spinlock_release(&p->lock);

CPU 结构

struct cpu {
    struct proc *proc;       // 当前进程
    struct proc idle;        // idle 进程

    u64 intr_state;          // 中断状态
    int intr_depth;          // 中断嵌套深度
    bool need_resched;       // 需要调度

    u8 idle_stack[IDLE_STACK_SIZE];  // idle 栈
};

上下文结构

struct context {
    u64 ra;    // 返回地址
    u64 sp;    // 栈指针
    u64 gp;    // 全局指针
    u64 s0-s11; // callee-saved 寄存器
    u64 sstatus; // CSR
};

最佳实践

持锁时间要短

// 正确
spinlock_acquire(&p->lock);
p->state = PROC_RUNNABLE;
spinlock_release(&p->lock);

// 错误:持锁时调度
spinlock_acquire(&p->lock);
sched_yield();  // 可能死锁
spinlock_release(&p->lock);

检查进程状态

if (p->state == PROC_ZOMBIE) {
    // 进程已退出
    free_proc(p);
}

正确使用调度

// 在中断上下文中设置标志
thiscpu()->need_resched = true;

// 在 kerneltrap 中检查
if (thiscpu()->need_resched) {
    sched_yield();
}