进程管理 - 理论讲解
1. 什么是进程?
进程 = 程序 + 执行状态
程序是静态的代码和数据,进程是程序的一次执行实例,包含:
- 代码段:要执行的指令
- 数据段:全局变量
- 栈:函数调用和局部变量
- 堆:动态分配的内存
- 寄存器状态:程序计数器(EIP)、栈指针(ESP)等
- 操作系统管理信息:PID、状态、页表等
2. 进程控制块(PCB)
PCB是操作系统表示进程的核心数据结构:
typedef enum {
PROCESS_READY, // 就绪
PROCESS_RUNNING, // 运行中
PROCESS_BLOCKED, // 等待I/O
PROCESS_TERMINATED // 已终止
} process_state_t;
typedef struct process {
uint32_t pid; // 唯一标识符
char name[32]; // 进程名
process_state_t state; // 当前状态
/* CPU上下文 */
uint32_t esp; // 栈指针
uint32_t eip; // 指令指针
uint32_t ebp; // 基址指针
uint32_t eflags; // 标志寄存器
/* 内存 */
page_directory_t *page_dir; // 独立的地址空间
uint32_t kernel_stack; // 内核态栈
uint32_t user_stack; // 用户态栈
/* 调度信息 */
uint32_t priority; // 优先级
uint32_t time_slice; // 剩余时间片
/* 链表 */
struct process *next;
} process_t;3. 进程生命周期
创建进程
1. 分配PID
2. 创建PCB
3. 分配内核栈
4. 创建页目录(继承内核映射)
5. 设置初始寄存器状态
6. 将进程加入就绪队列
上下文切换(简化版)
void context_switch(process_t *prev, process_t *next) {
// 1. 保存当前进程的寄存器到PCB
// 2. 切换页目录 (CR3)
// 3. 切换栈指针
// 4. 恢复下一个进程的寄存器
}销毁进程
1. 释放页目录和页表
2. 释放用户空间物理帧
3. 释放内核栈
4. 从进程链表中移除
5. 释放PCB
4. 内核栈 vs 用户栈
每个进程有两个栈:
┌──────────────────────┐ 高地址
│ 用户栈 │ ← 用户态代码使用
│ (Ring 3) │
├──────────────────────┤
│ ... │
├──────────────────────┤
│ 内核栈 │ ← 系统调用/中断时使用
│ (Ring 0) │
└──────────────────────┘ 低地址
为什么需要独立的内核栈?
- 安全: 用户不能篡改内核栈
- 隔离: 即使用户栈损坏,内核仍能正常工作
5. 进程链表管理
static process_t *process_list = NULL; // 所有进程
static process_t *ready_queue = NULL; // 就绪队列
static process_t *current = NULL; // 当前运行
static uint32_t next_pid = 1;
process_t *process_create(const char *name, void (*entry)(void)) {
process_t *proc = kmalloc(sizeof(process_t));
memset(proc, 0, sizeof(process_t));
proc->pid = next_pid++;
strncpy(proc->name, name, 31);
proc->state = PROCESS_READY;
// 分配4KB内核栈
proc->kernel_stack = (uint32_t)kmalloc_aligned(4096) + 4096;
// 设置初始上下文
proc->eip = (uint32_t)entry;
proc->esp = proc->kernel_stack;
proc->eflags = 0x202; // IF=1 (中断开启)
// 使用内核页目录(简化版,所有进程共享)
proc->page_dir = vmm_get_directory();
// 加入就绪队列
proc->next = ready_queue;
ready_queue = proc;
return proc;
}6. 第一个进程——idle任务
每个OS都需要一个”什么都不做”的空闲进程:
void idle_task(void) {
while (1) {
__asm__ volatile("hlt");
}
}
void process_init(void) {
// 创建idle进程(PID=0)
process_t *idle = process_create("idle", idle_task);
idle->pid = 0;
current = idle;
idle->state = PROCESS_RUNNING;
}下一步
进程结构建好了,但要让多个进程”同时”运行,需要调度器。下一章将实现定时器驱动的任务调度器!