第六章 进程 总结

来源:互联网 发布:网络交易管理办法解读 编辑:程序博客网 时间:2024/05/16 08:19

一、各个程序的作用

f程序,进程主体

g加入系统调用

h加入时间

i进程调度

三、下面分析f程序

1.关键结构体

[1]任务结构体

堆栈大小,任务名,任务函数

typedef    void  (*t_pf_task)              ();    

typedef struct s_task{

         t_pf_task initial_eip; //TestA,TestB,TestC

         int              stacksize;                   //0x8000,0x8000,0x8000

         char          name[32];         //"TestA","TestB","TestC"

}TASK;

 

 

[2]每个进程的结构体

每个进程有TSS,ldt选择子,2个LDT,pid和pidname

typedef struct s_proc{

         STACK_FRAME                            regs;        

         t_16                             ldt_sel;             

         DESCRIPTOR                      ldts[LDT_SIZE];         //LDT_SIZE=2,DESCRIPTOR8字节的描述符

         t_32                             pid;

         char                             p_name[16];   

}PROCESS;

 

typedef structs_stackframe {           /* proc_ptrpoints here                                                    ↑ Low                                         */

              t_32     gs;                      /*┓                                                                        │                                     */+0

              t_32     fs;                       /*┃                                                                        │                                     */+4

              t_32     es;                      /*┃                                                                        │                                     */+8

              t_32     ds;                      /*┃                                                                        │                                     */+12

              t_32     edi;                     /*┃                                                                        │                                     */+16

              t_32     esi;                     /*┣ pushed by save()                                                  │                       */+20

              t_32     ebp;                   /* ┃                                                                        │                                     */+24

              t_32     kernel_esp;    /* <-'popad' will ignore it                                  │                                     */+28

              t_32     ebx;                    /* ┃                                                ↑栈从高地址往低地址增长*/+32 

              t_32     edx;                    /* ┃                                                                        │                                     */+36

              t_32     ecx;                    /* ┃                                                                        │                                     */+40

              t_32     eax;                    /* ┛                                                                        │                                     */+44

              t_32     retaddr;           /*return address for assembly code save()            │                       */+48

              t_32     eip;                     /*  ┓                                                                                    │                       */+52

              t_32     cs;                       /*  ┃                                                                                    │                       */+56

              t_32     eflags;                             /*  ┣ these are pushed by CPU during interrupt             │         */+60

              t_32     esp;                    /*  ┃                                                                                    │                       */+64

              t_32     ss;                       /*  ┛                                                                                    ┷High              */+68

}STACK_FRAME;

/* 存储段描述符/系统段描述符 */

typedef structs_descriptor                /* 共 8 个字节 */

{

              t_16     limit_low;                       /*Limit */

              t_16     base_low;                      /*Base */

              t_8        base_mid;                     /*Base */

              t_8        attr1;                               /*P(1) DPL(2) DT(1) TYPE(4) */

              t_8        limit_high_attr2;         /*G(1) D(1) 0(1) AVL(1) LimitHigh(4) */

              t_8        base_high;                    /*Base */

}DESCRIPTOR;

三个进程PROCESS结构内容如下

 

TestA

save:

TestB

TestC

 

0x0004b5c0-0x4b624 101个字节

 

 

 

 

 

STACK_FRAME                            regs;        

 

 

 

 

 

+0     gs

0x19

0x19

 

 

 

+4     fs

0xd

0xd

 

 

 

+8     es

0xd

0xd

 

 

 

+12    ds

0xd

0xd

 

 

 

+16    edi

0x0

0xb4a

 

 

 

+20    esi

0x0后来设置成

0x31543

 

 

 

 

 

+24    ebp

0x0

0x4a89c

 

 

 

 

 

+28    kernel_esp

0x0

0x4b5f0

 

 

 

 

 

+32    ebx

0x0

0x0

 

 

 

 

 

+36    edx

0x0

0x0

 

 

 

 

 

+40    ecx

0x0

0x0

 

 

 

 

 

+44    eax

0x0

0x4a894

 

 

 

 

 

+48   retaddr

0x0

restart或者restart_reenter

 

 

 

 

 

+52   eip

0x000309e7 TestA函数

0x31438

 

 

 

 

 

+56   cs

0x5

0x5

 

 

 

 

 

+60   eflags

0x1202

0x1203

 

 

 

 

 

+64   esp

0x4a8c0

 

 

 

 

 

 

+68   ss

0xd

 

 

 

 

 

 

+72   t_16               ldt_sel

0x28

 

 

 

 

 

 

DESCRIPTOR    ldts[LDT_SIZE];

 

 

 

 

 

 

 

+74 第一个LDT

0x00cfb800  0x0000ffff

 

 

 

 

 

 

+82 第二个LDT

0x00cfb200  0x0000ffff

 

 

 

 

 

 

+90  t_32                                    pid;

0x00000000

 

 

 

 

 

 

+94  char                                    p_name[16];

00 00 54 65 73 74 41也就是TestA

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

3.TSS

typedef struct s_tss {

         t_32 backlink;

         t_32 esp0;                  /*stack pointer to use during interrupt */     

         t_32 ss0;           /*   "  segment  "  "   "        "     */

         t_32 esp1;

         x

         t_32 cr3;

         t_32 eip;

         t_32 flags;

         t_32 eax;

         t_32 ecx;

         t_32 edx;

         t_32 ebx;

         t_32 esp;

         t_32 ebp;

         t_32 esi;

         t_32 edi;

         t_32 es;

         t_32 cs;

         t_32 ss;

         t_32 ds;

         t_32 fs;

         t_32 gs;

         t_32 ldt;

         t_16 trap;

         t_16 iobase;     /*I/O位图基址大于或等于TSS段界限,就表示没有I/O许可位图 */

         /*t_8        iomap[2];*/

}TSS;

4.添加一个任务的步骤总结

下面我在f程序的基础上,增加一个进程D

(1)在添加一个进程体

Kernel\main.c

void TestD()

{

         int i = 0x3000;

         while(1){

                   disp_str("D");

                   disp_int(i++);

                   disp_str(".");

                   delay(1);

         }

}

(2)task_table中添加一项进程

Kernel\global.c

PUBLIC     TASK          task_table[NR_TASKS] = {{TestA,STACK_SIZE_TESTA, "TestA"},

                                               {TestB,STACK_SIZE_TESTB, "TestB"},

                                               {TestC,STACK_SIZE_TESTC, "TestC"},

                                               {TestD,STACK_SIZE_TESTD, "TestD"}};

(3)NR_TASKS1

Include\proc.h

#define NR_TASKS             4

 

(4)定义任务堆栈和修改STACK_SIZE_TOTAL

Include\proc.h

#define STACK_SIZE_TESTA     0x8000

#define STACK_SIZE_TESTB     0x8000

#define STACK_SIZE_TESTC     0x8000

#define STACK_SIZE_TESTD     0x8000

 

#define STACK_SIZE_TOTAL     (STACK_SIZE_TESTA+ \

                                     STACK_SIZE_TESTB+ \

                                     STACK_SIZE_TESTC+ \

                                     STACK_SIZE_TESTD)

 

(5)添加新任务执行体函数声明

Include\proto.h

void TestD();

 

 

四、分析g加入系统调用

f程序上增加的代码

1.kernel/syscall.asm

get_ticks:

         mov eax, _NR_get_ticks ; _NR_get_ticks

         int    INT_VECTOR_SYS_CALL  ; INT_VECTOR_SYS_CALL      equ  0x90

         ret

2. kernel/protect.c

//init_idt_desc_3102C(0x90, 0x8E,sys_call_307C6, 3);

init_idt_desc(INT_VECTOR_SYS_CALL,   DA_386IGate, sys_call,                     PRIVILEGE_USER);

 

3.当调用get_tichs就会调用sys_call函数,

Kernel/kernel.asm中

sys_call:

         call   save

         sti                       ;开中断

         call   [sys_call_table + eax * 4]    ;call   off_32098[eax*4] ,,off_32098存放的是sys_get_ticks函数

         mov [esi + EAXREG - P_STACKBASE], eax ;mov     [esi+2Ch], eax

         cli                        ;关中断

         ret

4.上面实际调用了call   [sys_call_table],也就是调用sys_call_table[0]

在kernel/global.c中有

PUBLIC     t_sys_call                   sys_call_table[NR_SYS_CALL] ={sys_get_ticks};

实际调用函数sys_get_ticks

 

5.kernel/proc.c

PUBLIC int sys_get_ticks()

{

         returnticks;

}

 

所以get_ticks最终调用的是sys_get_ticks函数

 

6.使用kernel/ main.c

void TestA()

{

         while(1){

                   disp_str("A");

                   disp_int(get_ticks());

                   disp_str(".");

                   delay(1);

         }

}

 

 

 

五、分析h加入时间

1.设置8253将时钟中断间隔改成10ms

Kernel\main.c

         out_byte(TIMER_MODE,RATE_GENERATOR);

         out_byte(TIMER0,(t_8) (TIMER_FREQ/HZ) );

         out_byte(TIMER0,(t_8) ((TIMER_FREQ/HZ) >> 8));

2. 延迟函数

Kernel\ clock.c

PUBLIC void milli_delay(int milli_sec)

{

         intt = get_ticks();

         while(((get_ticks()- t) * 1000 / HZ) < milli_sec) {}

}

3.使用

void TestA()

{

         while(1){

                   disp_str("A");

                   disp_int(get_ticks());

                   disp_str(".");

                   milli_delay(1000);  //延迟了1s

         }

}

4.注意

由于多进程切换和打印那些#字符导致不准确,去掉之后就好多了,还有bochs也不准确,换virtual pc就准确了,virtual pc更加像真机

 

5.为了测试我们改成一个进程

Kernel\global.c

PUBLIC     TASK          task_table[NR_TASKS] = {{TestA,STACK_SIZE_TESTA, "TestA"}};

Include\proc.h

#define NR_TASKS             1

 

#define STACK_SIZE_TESTA     0x8000

#define STACK_SIZE_TOTAL     (STACK_SIZE_TESTA)

显示结果,果然每次打印相隔1s,数值每次差别是100

六、分析i程序进程调度

根据延长的时间长短实现进程调度

在进程表中加入一个变量,

1.为进程表添加新的成员

Include/proc.h

Typedef struct s_proc{

……

Int    ticks;从某个值开始递减

Int    priority;prority=ticks永久不变

2.初始化

Kernel/main.c

proc_table[0].ticks =proc_table[0].priority = 15;

proc_table[1].ticks =proc_table[1].priority =  5;

proc_table[2].ticks =proc_table[2].priority =  3;

3进程调度函数

Kernel/proc.c

PUBLIC void schedule()

{

         PROCESS*         p;

         int              greatest_ticks = 0;

 

         while(!greatest_ticks) {

                   for(p=proc_table; p<proc_table+NR_TASKS; p++) {

                            if(p->ticks > greatest_ticks) {

                                     greatest_ticks= p->ticks;

                                     p_proc_ready= p;

                            }

                   }

 

                   if(!greatest_ticks) {

                            for (p=proc_table;p<proc_table+NR_TASKS; p++) {

                                     p->ticks= p->priority;

                            }

                   }

         }

}

4修改时钟中断处理函数

Kernel/clock.c

PUBLIC void clock_handler(int irq)

{

         p_proc_read->ticks--;//新加入

schedule();//新加入

}

0 0