/* By Marcus Xing kernel/proc.c 与进程有关的处理在此 */ #include "type.h" #include "const.h" #include "protect.h" #include "proc.h" #include "console.h" #include "tty.h" #include "global.h" #include "proto.h" /*------------------------------------------------------------------------Proc_A 进程A的执行体 */ void Proc_A() { int i = 0; while(1) { Printf("A:%x ",i++); Milli_Delay(200); } } /*------------------------------------------------------------------------Proc_B 进程B的执行体 */ void Proc_B() { while(1) { Milli_Delay(200); } } /*------------------------------------------------------------------------Proc_C 进程C的执行体 */ void Proc_C() { int i = 0x1000; while(1) { Printf("C "); Milli_Delay(200); } } /*----------------------------------------------------------------------Init_TSS 初始化TSS */ void Init_TSS() { tss.ss0 = SELECTOR_FLAT_RW; /* 指向GDT的FLAT_RW段 */ /* esp0不用急着填充 */ Fill_Desc(TSS_INDEX,(u32)&tss,sizeof(tss) - 1,DA_386TSS); tss.iobase = sizeof(tss); /* 没有许可位图 */ } /*----------------------------------------------------------------------Init_PCB 初始化与PCB的相关东东 */ void Init_PCB() { /* 当前进程个数赋值 */ d_Cur_Proc_Num = 4; PCB *p_Cur_PCB = PCB_Table; /* 指向第一个PCB */ Proc_Unique *p_Cur_Proc_Unique = Proc_Unique_Table; /* 指向第一个Proc_Unique */ u32 Proc_Stack_Top = (u32)All_Proc_Stack_Space; /* 定位各个进程的栈顶 */ u32 Selector_First_LDT_Index = SELECTOR_FIRST_LDT; /* 第一个进程的LDT在GDT的选择子 */ /* 填充各个进程的PCB */ int rpl; int dpl; int eflags; int i; for(i = 0;i < d_Cur_Proc_Num;i++) { /* 如果是系统进程,RPL为1,LDT中的DPL为1,标志寄存器为0x1202 如果是用户进程,RPL为3,LDT中的DPL为3,标志寄存器为0x3202 以上除去GS,GS始终指向GDT中的视频段,RPL为3 ss,ds,es,fs指向当前进程的LDT的FLAT_RW段 gs指向GDT中的视频段,RPL为1 cs指向当前进程的LDT的FLAT_C段 */ if(Is_System_Proc[i] == 1) { rpl = SA_RPL1; dpl = DA_DPL1; eflags = 0x1202; } else { rpl = SA_RPL3; dpl = DA_DPL3; eflags = 0x3202; } p_Cur_PCB->stack_frame.fs = SELECTOR_LDT_FLAT_RW + rpl + SA_TIL; p_Cur_PCB->stack_frame.gs = SELECTOR_VIDEO + SA_RPL3; p_Cur_PCB->stack_frame.es = SELECTOR_LDT_FLAT_RW + rpl + SA_TIL; p_Cur_PCB->stack_frame.ds = SELECTOR_LDT_FLAT_RW + rpl + SA_TIL; p_Cur_PCB->stack_frame.ss = SELECTOR_LDT_FLAT_RW + rpl + SA_TIL; p_Cur_PCB->stack_frame.cs = SELECTOR_LDT_FLAT_C + rpl + SA_TIL; p_Cur_PCB->proc_id = i; /* 进程号赋值 */ Str_Cpy(p_Cur_PCB->proc_name,p_Cur_Proc_Unique->proc_name); /* 进程名拷贝 */ /* esp指进程栈的栈顶 */ p_Cur_PCB->stack_frame.esp = Proc_Stack_Top + p_Cur_Proc_Unique->proc_stack_size; /* 为下一次赋值做准备 */ Proc_Stack_Top += p_Cur_Proc_Unique->proc_stack_size; /* eip指向进程体 */ p_Cur_PCB->stack_frame.eip = (u32)p_Cur_Proc_Unique->proc_exec_addr; /* eflags赋值 */ p_Cur_PCB->stack_frame.eflags = eflags; /* 当前进程的LDT在GDT的选择子赋值 */ p_Cur_PCB->LDT_Selector = Selector_First_LDT_Index; /* 复制GDT的FLAT_RW和FLAT_C段描述符到当前进程的LDT中 并把LDT的这两个描述符的DPL设为1 */ Memory_Copy(&p_Cur_PCB->LDT[0],&GDT[1],sizeof(Descriptor)); p_Cur_PCB->LDT[0].attr1 |= dpl; Memory_Copy(&p_Cur_PCB->LDT[1],&GDT[2],sizeof(Descriptor)); p_Cur_PCB->LDT[1].attr1 |= dpl; /* 填充此进程的LDT在GDT中的描述符 */ Fill_Desc(Selector_First_LDT_Index / 8,(u32)p_Cur_PCB->LDT,sizeof(Descriptor) * 2 - 1,DA_LDT); /* 为下一次赋值做准备 */ Selector_First_LDT_Index += 8; /* 指向下一个进程的PCB */ p_Cur_PCB++; /* 指向下一个进程的Proc_Unique */ p_Cur_Proc_Unique++; } /* 所有进程的ticks和priority的初始化 */ PCB_Table[0].ticks = PCB_Table[0].priority = 20; PCB_Table[1].ticks = PCB_Table[1].priority = 10; PCB_Table[2].ticks = PCB_Table[2].priority = 5; PCB_Table[3].ticks = PCB_Table[3].priority = 300; /* 设定各用户进程所绑定的TTY */ PCB_Table[0].bind_tty = 0; PCB_Table[1].bind_tty = 1; PCB_Table[2].bind_tty = 2; /* 初值赋0 */ d_Flag_Reenter = 0; /* 给p_Next_PCB赋值,指向第一个进程的PCB */ p_Next_PCB = PCB_Table; } /*----------------------------------------------------------------------Schedule 用于进程调度,Clock_Handler调用 */ void Schedule() { int greatest_ticks = 0; PCB *p_PCB; /* 所有进程的最大值<=0的话,一直循环下去 */ while(greatest_ticks <= 0) { /* 遍历所有PCB,把某个进程的最大ticks给greatest_ticks并切换进程 */ for(p_PCB = PCB_Table;p_PCB != PCB_Table + d_Cur_Proc_Num;p_PCB++) { if(p_PCB->ticks > greatest_ticks) { greatest_ticks = p_PCB->ticks; p_Next_PCB = p_PCB; } } /* 如果所有进程的ticks都用完, 遍历所以PCB,把某个进程的ticks赋回原值 */ if(greatest_ticks <= 0) { for(p_PCB = PCB_Table;p_PCB != PCB_Table + d_Cur_Proc_Num;p_PCB++) { p_PCB->ticks = p_PCB->priority; } } } }