diff --git a/docs/kernel/process_management/index.rst b/docs/kernel/process_management/index.rst index 5ab6b063..747f1aee 100644 --- a/docs/kernel/process_management/index.rst +++ b/docs/kernel/process_management/index.rst @@ -4,4 +4,5 @@ .. toctree:: :maxdepth: 1 - kthread \ No newline at end of file + kthread + pcb \ No newline at end of file diff --git a/docs/kernel/process_management/pcb.md b/docs/kernel/process_management/pcb.md new file mode 100644 index 00000000..9bea41e4 --- /dev/null +++ b/docs/kernel/process_management/pcb.md @@ -0,0 +1,27 @@ +# PCB 进程控制块 + +PCB的全称为process control block, 它是每个进程/线程的核心控制结构。定义于`kernel/src/process/proc-types.h`中。 + +## PCB详解 + +Todo: + +## 与PCB的管理相关的API + +### 根据pid寻找pcb + +**process_find_pcb_by_pid** + +该API提供了根据pid寻找pcb的功能,定义在`kernel/src/process/process.h`中。 + +当找到目标的pcb时,返回对应的pcb,否则返回NULL。 + +#### 参数 + +**pid** + 进程id + +#### 返回值 + +**struct process_control_block** + 目标pcb \ No newline at end of file diff --git a/kernel/src/process/proc-types.h b/kernel/src/process/proc-types.h index 256ac932..a7ce7c2b 100644 --- a/kernel/src/process/proc-types.h +++ b/kernel/src/process/proc-types.h @@ -84,7 +84,7 @@ struct process_control_block // 进程切换时保存的状态信息 struct thread_struct *thread; - // 连接各个pcb的双向链表 + // pcb加入调度队列时,所使用的链表节点 struct List list; //todo:给pcb中加一个spinlock_t成员 @@ -105,7 +105,7 @@ struct process_control_block struct vfs_file_t *fds[PROC_MAX_FD_NUM]; // 链表中的下一个pcb - struct process_control_block *next_pcb; + struct process_control_block *prev_pcb, *next_pcb; // 父进程的pcb struct process_control_block *parent_pcb; diff --git a/kernel/src/process/process.c b/kernel/src/process/process.c index 15c2ac0b..dbd4b5a9 100644 --- a/kernel/src/process/process.c +++ b/kernel/src/process/process.c @@ -676,7 +676,7 @@ unsigned long do_fork(struct pt_regs *regs, unsigned long clone_flags, unsigned struct process_control_block *tsk = NULL; // 为新的进程分配栈空间,并将pcb放置在底部 - tsk = (struct process_control_block *)kmalloc(STACK_SIZE, 0); + tsk = (struct process_control_block *)kzalloc(STACK_SIZE, 0); barrier(); if (tsk == NULL) @@ -717,6 +717,9 @@ unsigned long do_fork(struct pt_regs *regs, unsigned long clone_flags, unsigned tsk->pid = process_global_pid++; barrier(); // 加入到进程链表中 + // todo: 对pcb_list_lock加锁 + tsk->prev_pcb = &initial_proc_union.pcb; + barrier(); tsk->next_pcb = initial_proc_union.pcb.next_pcb; barrier(); initial_proc_union.pcb.next_pcb = tsk; @@ -779,13 +782,14 @@ copy_flags_failed:; } /** - * @brief 根据pid获取进程的pcb + * @brief 根据pid获取进程的pcb。存在对应的pcb时,返回对应的pcb的指针,否则返回NULL * * @param pid * @return struct process_control_block* */ -struct process_control_block *process_get_pcb(long pid) +struct process_control_block *process_find_pcb_by_pid(pid_t pid) { + // todo: 当进程管理模块拥有pcblist_lock之后,对其加锁 struct process_control_block *pcb = initial_proc_union.pcb.next_pcb; // 使用蛮力法搜索指定pid的pcb @@ -797,6 +801,7 @@ struct process_control_block *process_get_pcb(long pid) } return NULL; } + /** * @brief 将进程加入到调度器的就绪队列中 * @@ -1174,8 +1179,15 @@ int process_release_pcb(struct process_control_block *pcb) { // 释放子进程的页表 process_exit_mm(pcb); - if ((pcb->flags & PF_KTHREAD)) // 释放内核线程的worker private结构体 + if ((pcb->flags & PF_KTHREAD)) // 释放内核线程的worker private结构体 free_kthread_struct(pcb); + + // 将pcb从pcb链表中移除 + // todo: 对相关的pcb加锁 + pcb->prev_pcb->next_pcb = pcb->next_pcb; + pcb->next_pcb->prev_pcb = pcb->prev_pcb; + + // 释放当前pcb kfree(pcb); return 0; } diff --git a/kernel/src/process/process.h b/kernel/src/process/process.h index a8543d85..b3a2aaf5 100644 --- a/kernel/src/process/process.h +++ b/kernel/src/process/process.h @@ -27,7 +27,7 @@ { \ .state = PROC_UNINTERRUPTIBLE, .flags = PF_KTHREAD, .preempt_count = 0, .signal = 0, .cpu_id = 0, \ .mm = &initial_mm, .thread = &initial_thread, .addr_limit = 0xffffffffffffffff, .pid = 0, .priority = 2, \ - .virtual_runtime = 0, .fds = {0}, .next_pcb = &proc, .parent_pcb = &proc, .exit_code = 0, \ + .virtual_runtime = 0, .fds = {0}, .next_pcb = &proc, .prev_pcb = &proc, .parent_pcb = &proc, .exit_code = 0, \ .wait_child_proc_exit = 0, .worker_private = NULL, .policy = SCHED_NORMAL \ } @@ -95,12 +95,12 @@ unsigned long do_fork(struct pt_regs *regs, unsigned long clone_flags, unsigned unsigned long stack_size); /** - * @brief 根据pid获取进程的pcb + * @brief 根据pid获取进程的pcb。存在对应的pcb时,返回对应的pcb的指针,否则返回NULL * * @param pid * @return struct process_control_block* */ -struct process_control_block *process_get_pcb(long pid); +struct process_control_block *process_find_pcb_by_pid(pid_t pid); /** * @brief 将进程加入到调度器的就绪队列中 diff --git a/kernel/src/syscall/syscall.c b/kernel/src/syscall/syscall.c index 225c4bb6..0e20b627 100644 --- a/kernel/src/syscall/syscall.c +++ b/kernel/src/syscall/syscall.c @@ -518,14 +518,8 @@ uint64_t sys_wait4(struct pt_regs *regs) // 查找pid为指定值的进程 // ps: 这里判断子进程的方法没有按照posix 2008来写。 // todo: 根据进程树判断是否为当前进程的子进程 - for (proc = &initial_proc_union.pcb; proc->next_pcb != &initial_proc_union.pcb; proc = proc->next_pcb) - { - if (proc->next_pcb->pid == pid) - { - child_proc = proc->next_pcb; - break; - } - } + + child_proc = process_find_pcb_by_pid(pid); if (child_proc == NULL) return -ECHILD; @@ -542,7 +536,6 @@ uint64_t sys_wait4(struct pt_regs *regs) if (likely(status != NULL)) *status = child_proc->exit_code; // copy_to_user(status, (void*)child_proc->exit_code, sizeof(int)); - proc->next_pcb = child_proc->next_pcb; process_release_pcb(child_proc); return 0;