【第6章】改进多进程

     上篇文章中我们虽然实现了多进程,但是要扩展起来就太麻烦了。如果我们要新加一个进程,就得添加进程体,添加进程堆栈空间,将PCB表的个数加1,在Init_PCB函数中复制一大段代码来填充新加进程的PCB,这样显得不够优雅,特别是最后一段代码中重复的代码比较多,进程与进程之间的区别无非就是执行体和堆栈不同而已,按照书中作者的做法,是把这两样东东作为一个新的结构的成员,作者也是模仿MINIX的做法罢了。

      我们下面就来做吧,我们还是只有两个进程。下面在proc.h中定义一个TASK结构,就是用来存放各进程的执行体的地址和堆栈地址:

Code:
  1. typedef struct s_task  
  2. {  
  3.     Task_Func eip;  
  4.     u32 stack_size;  
  5. }TASK;  

   其中task_f是新定义的类型,定义在type.h中:

Code:
  1. typedef void (*Task_Func)();  

   接着就要声明和定义一个TASK类型的结构数组了,显然有多少个进程这个数组就应该有多少个TASK,为了方便引用进程的个数,在proc.h中定义一个表示进程数量的宏:

Code:
  1. #define PROC_NUM        2 

   OK,来到global.h和global.c中定义一个TASK类型的结构数组:

Code:
  1. extern TASK Task_Tables[];  /* in global.h */  
Code:
  1. #include "proto.h"
  2. TASK Task_Tables[PROC_NUM] = { {Proc_A,PROC_A_STACK_SIZE},  
  3.                                {Proc_B,PROC_B_STACK_SIZE}  
  4.                              };  /* in global.c */ 

   在global.c中,由于在定义中用到进程的执行体的函数名,所以要包含proto.h头文件,在MAKEFILE中也要作相应修改,PROC_A_STACK_SIZE和PROC_A_STACK_SIZE定义在proc.h中,代表该进程的堆栈大小

Code:
  1. # #define PROC_NUM        2    
  2. # #define PROC_A_STACK_SIZE       0x8000    
  3. # #define PROC_B_STACK_SIZE       0x8000    
  4. # #define PROC_STACK_SIZE_TOTAL       (PROC_A_STACK_SIZE + /    
  5.                                        PROC_B_STACK_SIZE)  

   其中,PROC_STACK_SIZE_TOTAL是进程堆栈空间的总和,我们也不再每添加一个进程就添加一个堆栈空间了,而是统一分配到一个数组空间去,在global.h和global.c中做相应修改,把Proc_A_Stack和Proc_B_Stack的声明和定义分别删掉,添加总的堆栈空间:

Code:
  1. extern u8 Proc_Stack_Space_Total[];   /* in global.h */  
Code:
  1. u8 Proc_Stack_Space_Total[PROC_STACK_SIZE_TOTAL];  /* in global.c */  

   接下来就改动填充进程相应的PCB的部分了,用一个循环就可以减少重复的代码,在Init_PCB中把原来的代码全部删掉,再来添加:

Code:
  1. void Init_PCB()  
  2. {  
  3.     PCB *p_Cur_PCB = PCB_Tables;  
  4.     TASK *p_Cur_Task = Task_Tables;  
  5.     u8 *p_Cur_Top_Of_Stack = Proc_Stack_Space_Total + PROC_STACK_SIZE_TOTAL;  
  6.     u16 Cur_LDT_Index = INDEX_OF_FIRST_LDT;  
  7.     u32 i;  
  8.           
  9.     for(i = 0 ; i < PROC_NUM ; i++)  
  10.     {  
  11.         Memory_Set(p_Cur_PCB,sizeof(PCB),0);  
  12.         Memory_Copy(&GDT[1],&p_Cur_PCB->ldts[0],sizeof(Descriptor));  
  13.         Memory_Copy(&GDT[2],&p_Cur_PCB->ldts[1],sizeof(Descriptor));  
  14.         p_Cur_PCB->ldts[0].attr1 &= 0x9f;  
  15.         p_Cur_PCB->ldts[0].attr1 |= DA_DPL1;  
  16.         p_Cur_PCB->ldts[1].attr1 &= 0x9f;  
  17.         p_Cur_PCB->ldts[1].attr1 |= DA_DPL1;  
  18.         p_Cur_PCB->stack_frame.ds = 0 + 4 + 1;  
  19.         p_Cur_PCB->stack_frame.es = 0 + 4 + 1;   
  20.         p_Cur_PCB->stack_frame.gs = 24 + 1 ;   
  21.         p_Cur_PCB->stack_frame.fs = 0 + 4 + 1;   
  22.         p_Cur_PCB->stack_frame.ss = 0 + 4 + 1;   
  23.         p_Cur_PCB->stack_frame.esp = (u32)p_Cur_Top_Of_Stack;   
  24.         p_Cur_PCB->stack_frame.cs = 8 + 4 + 1;   
  25.         p_Cur_PCB->stack_frame.eip = (u32)p_Cur_Task->eip;   
  26.         p_Cur_PCB->stack_frame.eflags = 0x1202;   
  27.         p_Cur_PCB->LDT_Selector = (Cur_LDT_Index << 3);  
  28.         Fill_Desc(Cur_LDT_Index,(u32)p_Cur_PCB->ldts,sizeof(Descriptor) * 2 - 1,DA_LDT);  
  29.               
  30.         p_Cur_Top_Of_Stack -= p_Cur_Task->stack_size;  
  31.         p_Cur_PCB++;  
  32.         p_Cur_Task++;  
  33.         Cur_LDT_Index++;  
  34.     }  
  35.           
  36.     p_Resume_PCB = PCB_Tables;  
  37. }  

   其中,INDEX_OF_FIRST_LDT是在proc.h中定义的宏,捎带把INDEX_OF_TSS也定义上:

Code:
  1. #define INDEX_OF_TSS                4     
  2. #define INDEX_OF_FIRST_LDT          5  

   把相关的地方一下修改,在C_Start中:

Code:
  1. Fill_Desc(INDEX_OF_TSS,(u32)&tss,sizeof(tss) - 1,DA_386TSS);  

   好了,编译链接,结果与前一节相同,但我们的程序已经更加容易扩展了。

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值