1 /** 2 * @file process.h 3 * @author longjin 4 * @brief 进程 5 * @date 2022-01-29 6 * 7 * @copyright Copyright (c) 2022 8 * 9 */ 10 11 #pragma once 12 #include "ptrace.h" 13 #include <common/cpu.h> 14 #include <common/errno.h> 15 #include <common/glib.h> 16 #include <common/wait_queue.h> 17 #include <filesystem/vfs/VFS.h> 18 #include <mm/mm-types.h> 19 #include <syscall/syscall.h> 20 21 #include <asm/current.h> 22 23 #include "proc-types.h" 24 25 extern void process_exit_thread(struct process_control_block *pcb); 26 extern int process_exit_files(struct process_control_block *pcb); 27 28 /** 29 * @brief 任务状态段结构体 30 * 31 */ 32 33 // 设置初始进程的tss 34 #define INITIAL_TSS \ 35 { \ 36 .reserved0 = 0, .rsp0 = (ul)(initial_proc_union.stack + STACK_SIZE / sizeof(ul)), \ 37 .rsp1 = (ul)(initial_proc_union.stack + STACK_SIZE / sizeof(ul)), \ 38 .rsp2 = (ul)(initial_proc_union.stack + STACK_SIZE / sizeof(ul)), .reserved1 = 0, .ist1 = 0xffff800000007c00, \ 39 .ist2 = 0xffff800000007c00, .ist3 = 0xffff800000007c00, .ist4 = 0xffff800000007c00, \ 40 .ist5 = 0xffff800000007c00, .ist6 = 0xffff800000007c00, .ist7 = 0xffff800000007c00, .reserved2 = 0, \ 41 .reserved3 = 0, .io_map_base_addr = 0 \ 42 } 43 44 #define GET_CURRENT_PCB \ 45 "movq %rsp, %rbx \n\t" \ 46 "andq $-32768, %rbx\n\t" 47 48 /** 49 * @brief 切换进程上下文 50 * 先把rbp和rax保存到栈中,然后将rsp和rip保存到prev的thread结构体中 51 * 然后调用__switch_to切换栈,配置其他信息,最后恢复下一个进程的rax rbp。 52 */ 53 54 #define switch_to(prev, next) \ 55 do \ 56 { \ 57 __asm__ __volatile__("pushq %%rbp \n\t" \ 58 "pushq %%rax \n\t" \ 59 "movq %%rsp, %0 \n\t" \ 60 "movq %2, %%rsp \n\t" \ 61 "leaq 2f(%%rip), %%rax \n\t" \ 62 "movq %%rax, %1 \n\t" \ 63 "pushq %3 \n\t" \ 64 "jmp __switch_to \n\t" \ 65 "2: \n\t" \ 66 "popq %%rax \n\t" \ 67 "popq %%rbp \n\t" \ 68 : "=m"(prev->thread->rsp), "=m"(prev->thread->rip) \ 69 : "m"(next->thread->rsp), "m"(next->thread->rip), "D"(prev), "S"(next) \ 70 : "memory", "rax"); \ 71 } while (0) 72 73 /** 74 * @brief 初始化系统的第一个进程 75 * 76 */ 77 void process_init(); 78 79 /** 80 * @brief fork当前进程 81 * 82 * @param regs 新的寄存器值 83 * @param clone_flags 克隆标志 84 * @param stack_start 堆栈开始地址 85 * @param stack_size 堆栈大小 86 * @return unsigned long 87 */ 88 unsigned long do_fork(struct pt_regs *regs, unsigned long clone_flags, unsigned long stack_start, 89 unsigned long stack_size); 90 91 /** 92 * @brief 根据pid获取进程的pcb。存在对应的pcb时,返回对应的pcb的指针,否则返回NULL 93 * 当进程管理模块拥有pcblist_lock之后,调用本函数之前,应当对其加锁 94 * @param pid 95 * @return struct process_control_block* 96 */ 97 struct process_control_block *process_find_pcb_by_pid(pid_t pid); 98 99 /** 100 * @brief 将进程加入到调度器的就绪队列中 101 * 102 * @param pcb 进程的pcb 103 * 104 * @return 如果进程被成功唤醒,则返回1,如果进程正在运行,则返回0.如果pcb为NULL,则返回-EINVAL 105 */ 106 int process_wakeup(struct process_control_block *pcb); 107 108 /** 109 * @brief 将进程加入到调度器的就绪队列中,并标志当前进程需要被调度 110 * 111 * @param pcb 进程的pcb 112 */ 113 int process_wakeup_immediately(struct process_control_block *pcb); 114 115 /** 116 * @brief 使当前进程去执行新的代码 117 * 118 * @param regs 当前进程的寄存器 119 * @param path 可执行程序的路径 120 * @param argv 参数列表 121 * @param envp 环境变量 122 * @return ul 错误码 123 */ 124 ul do_execve(struct pt_regs *regs, char *path, char *argv[], char *envp[]); 125 126 /** 127 * @brief 释放进程的页表 128 * 129 * @param pcb 要被释放页表的进程 130 * @return uint64_t 131 */ 132 uint64_t process_exit_mm(struct process_control_block *pcb); 133 134 /** 135 * @brief 进程退出时执行的函数 136 * 137 * @param code 返回码 138 * @return ul 139 */ 140 ul process_do_exit(ul code); 141 142 /** 143 * @brief 当子进程退出后向父进程发送通知 144 * 145 */ 146 void process_exit_notify(); 147 148 /** 149 * @brief 初始化内核进程 150 * 151 * @param fn 目标程序的地址 152 * @param arg 向目标程序传入的参数 153 * @param flags 154 * @return int 155 */ 156 157 pid_t kernel_thread(int (*fn)(void *), void *arg, unsigned long flags); 158 159 int process_fd_alloc(struct vfs_file_t *file); 160 161 int process_release_pcb(struct process_control_block *pcb); 162 163 /** 164 * @brief 切换页表 165 * @param prev 前一个进程的pcb 166 * @param next 下一个进程的pcb 167 * 168 */ 169 #define process_switch_mm(next_pcb) \ 170 do \ 171 { \ 172 asm volatile("movq %0, %%cr3 \n\t" ::"r"(next_pcb->mm->pgd) : "memory"); \ 173 } while (0) 174 // flush_tlb(); 175 176 // 获取当前cpu id 177 #define proc_current_cpu_id (current_pcb->cpu_id) 178 179 extern unsigned long head_stack_start; // 导出内核层栈基地址(定义在head.S) 180 extern ul _stack_start; 181 extern void ret_from_intr(void); // 导出从中断返回的函数(定义在entry.S) 182 183 extern struct tss_struct initial_tss[MAX_CPU_NUM]; 184 extern struct mm_struct initial_mm; 185 extern struct thread_struct initial_thread; 186 extern union proc_union initial_proc_union; 187 extern struct process_control_block *initial_proc[MAX_CPU_NUM]; 188 189 /** 190 * @brief 给pcb设置名字 191 * 192 * @param pcb 需要设置名字的pcb 193 * @param pcb_name 保存名字的char数组 194 */ 195 void process_set_pcb_name(struct process_control_block *pcb, const char *pcb_name); 196 197 /** 198 * @brief 判断进程是否已经停止 199 * 200 * hint: 本函数在rust中实现,请参考rust版本的注释 201 * 202 * @param pcb 目标pcb 203 * @return true 204 * @return false 205 */ 206 extern bool process_is_stopped(struct process_control_block *pcb); 207 208 /** 209 * @brief 尝试唤醒指定的进程。 210 * 本函数的行为:If (@_state & @pcb->state) @pcb->state = TASK_RUNNING. 211 * 212 * hint: 本函数在rust中实现,请参考rust版本的注释 213 */ 214 extern int process_try_to_wake_up(struct process_control_block *_pcb, uint64_t _state, int32_t _wake_flags); 215 216 /** @brief 当进程,满足 (@state & @pcb->state)时,唤醒进程,并设置: @pcb->state = TASK_RUNNING. 217 * 218 * hint: 本函数在rust中实现,请参考rust版本的注释 219 * @return true 唤醒成功 220 * @return false 唤醒失败 221 */ 222 extern int process_wake_up_state(struct process_control_block *pcb, uint64_t state); 223 void __switch_to(struct process_control_block *prev, struct process_control_block *next); 224