📄 fork.c
字号:
#include <fairysky/defs.h>#include <fairysky/types.h>#include <fairysky/kernel.h>#include <asm/system.h>#include <fairysky/string.h>#include <fairysky/scheduler.h>#include <fairysky/system_call.h>#include <fairysky/errno.h>#include <asm/memory.h>extern void add_run_queue(task_struct_t *task);extern task_struct_t *current;extern s32 last_pid;void verify_area(void * addr, size_t size){}//获取空闲的pidstatic s32 get_free_pid(){ task_struct_t *tmp;getnextpid: ++last_pid; if (last_pid == 0) { last_pid = 1; } TASK_EACH(sleep_task, tmp) { if (tmp->pid == last_pid) { goto getnextpid; } } TASK_EACH(pinit_task, tmp) { if (tmp->pid == last_pid) { goto getnextpid; } } return last_pid;}//复制一个进程的全部空间,复制页目录和页表//from_page_dir:父进程的页目录地址//to_page_dir:进程的页目录地址static void copy_mem(u32 to_page_dir, u32 from_page_dir){ if (copy_page_table(to_page_dir, from_page_dir)) { panic("copy_mem failure\n"); }}#ifdef WINDOWS_CYGWIN #define CHILD_RET_FROM_SYS_CALL child_ret_from_sys_call#else #define CHILD_RET_FROM_SYS_CALL _child_ret_from_sys_call#endifextern void CHILD_RET_FROM_SYS_CALL();//系统调用fork的实现//这里不再处理子进程的返回值了,在子进程第一次进入ring3时处理,//具体在_child_ret_from_sys_call,在system_call_entry.asm文件中pid_t sys_fork( long EBX, long ECX, long EDX, long ESI, long EDI, long EBP, long FS, long GS, long ES, long DS, long EIP, long CS, long EFLAG, long ESP3, long SS3){ addr_t *ptmp; task_struct_t *tmp_task = NULL; //分配pcb空间,4k int index = get_free_page(); if (! index) { return ENOMEM; } tmp_task = (task_struct_t *) index_to_vaddr(index); //memset(tmp_task, 0, sizeof(task_struct_t)); index = get_free_page(); //分配进程的页目录 if (!index) { free_page((u32) tmp_task); //如果失败,则释放pcb空间 return -1; } INIT_LIST_HEAD(&(tmp_task->list)); *tmp_task = *current; tmp_task->state = TASK_STOPPED; //复制父进程的页目录和页表 copy_mem(index_to_vaddr(index), paddr_to_vaddr(current->tss.cr3)); //复制父进程的堆栈给子进程,但EAX修改为0,以下代码先实现之,以后再优化 ptmp = (addr_t *)((u8 *)tmp_task + PAGE_SIZE - 4); *ptmp-- = SS3 & 0x00FF; //0ffc *ptmp-- = ESP3; //0ff8 *ptmp-- = EFLAG; //0ff4 *ptmp-- = CS & 0x00FF; //0ff0 *ptmp-- = EIP; //0fec *ptmp-- = DS & 0x00FF; //0fe8 *ptmp-- = ES & 0x00FF; //0fe4 *ptmp-- = GS & 0x00FF; //0fe0 *ptmp-- = FS & 0x00FF; //0fdc *ptmp-- = EBP; //0fd8 *ptmp-- = EDI; //0fd4 *ptmp-- = ESI; //0fd0 *ptmp-- = EDX; //0fcc *ptmp-- = ECX; //0fc8 *ptmp = EBX; //0fc4 //子进程的页目录地址 tmp_task->tss.cr3 = (u32)index_to_paddr(index); tmp_task->tss.esp0 = (u32)ptmp;// tmp_task + PAGE_SIZE; tmp_task->tss.eip = (u32)CHILD_RET_FROM_SYS_CALL; //因为是子进程,所以当被调度时,直接从这里运行返回用户空间 tmp_task->state = TASK_RUNNING; //进程状态 tmp_task->counter = current->counter / 2; //运行时间片,对进程0来说是没有用的,只有没有其他进程可调度的情况下才会调度进程0 tmp_task->priority = current->priority; //优先级,对进程0来说也没有用的 tmp_task->uid = tmp_task->euid = tmp_task->suid = 0; tmp_task->gid = tmp_task->egid = tmp_task->sgid = 0; tmp_task->signal = 0; //信号,按位 tmp_task->signal_blocked = 0; //被掩码的信号,位图 tmp_task->pid = get_free_pid(); //进程的pid tmp_task->pgrp = 0; //组id tmp_task->session = 0; // tmp_task->leader = 0; // tmp_task->p_original_parent = current; //原始的父进程 tmp_task->p_parent = current; //父进程 tmp_task->p_child = NULL; //子进程 tmp_task->p_younger_sibling = NULL; //弟进程 tmp_task->p_older_sibling = current->p_child; //兄进程 if (tmp_task->p_older_sibling) { //如果存在兄进程,则给兄进程设置弟进程 tmp_task->p_older_sibling->p_younger_sibling = tmp_task; } tmp_task->uid = 0; //用户id tmp_task->euid = 0; //有效用户id tmp_task->suid = 0; //保存的用户id,好像没有用啊 tmp_task->gid = 0; //组id tmp_task->egid = 0; //有效组id tmp_task->sgid = 0; //保存的组id tmp_task->alarm = 0; tmp_task->user_time = 0; //用户态运行时间(滴答数) tmp_task->system_time = 0; //内核态运行时间(滴答数) //cutime, //子进程用户态运行时间(滴答数),好像没有用啊 //cstime, //子进程内核态运行时间(滴答数),好像没有用啊 tmp_task->start_time = 0; //进程开始的时间 tmp_task->rss = 0; //常驻内存的页面数,暂时不用 tmp_task->tty = -1; //如果等于-1,则表示没有tty tmp_task->umask = 0; //文件创建属性屏蔽位 tmp_task->pwd = NULL; //当前工作目录i节点 tmp_task->root = NULL; //根目录i节点 tmp_task->executable = NULL; //执行文件i节点 tmp_task->original_esp0 = (u32)tmp_task + PAGE_SIZE; current->p_child = tmp_task; cli(); add_run_queue(tmp_task); //加入可调度任务队列 sti(); return tmp_task->pid; //返回子进程的pid}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -