85 void TestB() 86 { 87 int i = 0x1000; 88 while(1){ 89 disp_str("B"); 90 disp_int(i++); 91 disp_str("."); 92 delay(1); 93 } 94 }
42 typedef struct s_task { 43 t_pf_task initial_eip;函数指针,指向进程入口 44 int stacksize; 45 char name[32]; 46 }TASK; 在global.c中增加进程信息数组的定义,然后在global.h中进行申明 20 PUBLIC char task_stack[STACK_SIZE_TOTAL];注意,task_stack是char数组 21 22 PUBLIC TASK task_table[NR_TASKS] = {{TestA, STACK_SIZE_TESTA, "TestA"}, 23 {TestB, STACK_SIZE_TESTB, "TestB"}, 24 {TestC, STACK_SIZE_TESTC, "TestC"}};我们需要在proc.h中添加对stack_size_testA等的定义,另外增加NR_TASKS
20 PUBLIC int tinix_main() 21 { 22 disp_str("-----\"tinix_main\" begins-----\n"); 23 24 TASK* p_task = task_table; 25 PROCESS* p_proc = proc_table; 26 char* p_task_stack = task_stack + STACK_SIZE_TOTAL; 27 t_16 selector_ldt = SELECTOR_LDT_FIRST; 28 int i; 29 for(i=0;i<NR_TASKS;i++){ 30 strcpy(p_proc->p_name, p_task->name); // name of the process 31 p_proc->pid = i; // pid 32 33 p_proc->ldt_sel = selector_ldt; 34 memcpy(&p_proc->ldts[0], &gdt[SELECTOR_KERNEL_CS >> 3], sizeof(DESCRIPTOR)); 35 p_proc->ldts[0].attr1 = DA_C | PRIVILEGE_TASK << 5; // change the DPL 36 memcpy(&p_proc->ldts[1], &gdt[SELECTOR_KERNEL_DS >> 3], sizeof(DESCRIPTOR)); 37 p_proc->ldts[1].attr1 = DA_DRW | PRIVILEGE_TASK << 5; // change the DPL 38 p_proc->regs.cs = ((8 * 0) & SA_RPL_MASK & SA_TI_MASK) | SA_TIL | RPL_TASK; 39 p_proc->regs.ds = ((8 * 1) & SA_RPL_MASK & SA_TI_MASK) | SA_TIL | RPL_TASK; 40 p_proc->regs.es = ((8 * 1) & SA_RPL_MASK & SA_TI_MASK) | SA_TIL | RPL_TASK; 41 p_proc->regs.fs = ((8 * 1) & SA_RPL_MASK & SA_TI_MASK) | SA_TIL | RPL_TASK; 42 p_proc->regs.ss = ((8 * 1) & SA_RPL_MASK & SA_TI_MASK) | SA_TIL | RPL_TASK; 43 p_proc->regs.gs = (SELECTOR_KERNEL_GS & SA_RPL_MASK) | RPL_TASK; 44 p_proc->regs.eip = (t_32)p_task->initial_eip; 45 p_proc->regs.esp = (t_32)p_task_stack; 46 p_proc->regs.eflags = 0x1202; // IF=1, IOPL=1, bit 2 is always 1. 47 48 p_task_stack -= p_task->stacksize; 49 p_proc++; 50 p_task++; 51 selector_ldt += 1 << 3; 52 } 53 54 k_reenter = 0; 55 56 p_proc_ready = proc_table; 57 58 put_irq_handler(CLOCK_IRQ, clock_handler); /* 设定时钟中断处理程序 */ 59 enable_irq(CLOCK_IRQ); /* 让8259A可以接收时钟中断 */ 60 61 restart(); 62 63 64 while(1){} 65 }
108 /* 填充 GDT 中每个进程的 LDT 的描述符 */ 109 int i; 110 PROCESS* p_proc = proc_table; 111 t_16 selector_ldt = INDEX_LDT_FIRST << 3; 112 for(i=0;i<NR_TASKS;i++){ 113 init_descriptor(&gdt[selector_ldt>>3], 114 vir2phys(seg2phys(SELECTOR_KERNEL_DS), proc_table[i].ldts), 115 LDT_SIZE * sizeof(DESCRIPTOR) - 1, 116 DA_LDT); 117 p_proc++; 118 selector_ldt += 1 << 3; 119 }
离开内核栈,将esp指向PCB: mov esp,[p_proc_ready]
p_proc_ready是一个指针,我们仅仅需要改变这个指针就ok。
现在,我们创建一个中断服务程序(此处仅仅是处理服务部分,不包括上下文切换和中断控制部分)///kernel/clock.c 20 PUBLIC void clock_handler(int irq) 21 { 22 disp_str("#"); 28 29 p_proc_ready++; 30 31 if (p_proc_ready >= proc_table + NR_TASKS) { 32 p_proc_ready = proc_table; 33 } 34 }
179 180 sti 181 182 push 0 183 call clock_handler;注意这句 184 add esp, 4 185 186 cli 187 188 mov esp, [p_proc_ready] ; 离开内核栈;下面的几句,虽然与之前没有代码上的改变,但是由于clock_hander内部使用了全局变量,所以下面几句的实际数值发生了改变 189 lldt [esp + P_LDT_SEL];改变ldtr 190 lea eax, [esp + P_STACKTOP] 191 mov dword [tss + TSS3_S_SP0], eax 192 193 .re_enter: ; 如果(k_reenter != 0),会跳转到这里 194 dec dword [k_reenter] ; k_reenter--;
《自己动手写操作系统 》第六章 多进程,布布扣,bubuko.com
原文:http://blog.csdn.net/trochiluses/article/details/21984297