09保护模式下的进程调度.docx

上传人:b****2 文档编号:2434986 上传时间:2022-10-29 格式:DOCX 页数:39 大小:2.39MB
下载 相关 举报
09保护模式下的进程调度.docx_第1页
第1页 / 共39页
09保护模式下的进程调度.docx_第2页
第2页 / 共39页
09保护模式下的进程调度.docx_第3页
第3页 / 共39页
09保护模式下的进程调度.docx_第4页
第4页 / 共39页
09保护模式下的进程调度.docx_第5页
第5页 / 共39页
点击查看更多>>
下载资源
资源描述

09保护模式下的进程调度.docx

《09保护模式下的进程调度.docx》由会员分享,可在线阅读,更多相关《09保护模式下的进程调度.docx(39页珍藏版)》请在冰豆网上搜索。

09保护模式下的进程调度.docx

09保护模式下的进程调度

0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000保护模式下的进程调度

本实验采用C与汇编语言混合编程,利用计时中断实现保护模式下多个进程间的简单切换。

1程序结构

1.1运行过程

●系统加电或重启-------------------------------------------

●系统初始化系统BIOS例程

●加载引导扇区

●控制权交给引导扇区--------------------------------------

●加载loader引导扇区(BOOT5)

●跳转到loader------------------------------------------------

●获取并显示内存信息

●定义并初始化GDT

●进入保护模式装载(LOADER)

●启动分页机制

●加载kernel

●跳转到kernel------------------------------------------------

●切换到内核GDT内核(KERNEL)

●初始化8259A************************

●初始化IDTprotect.c:

init_prot()*

●在GDT中添加TSS和3个LDT描述符*

●初始化TSS**************************

●初始化进程表************************

●设置时钟中断处理程序*

●打开时钟中断main.c:

kerel_main()*

●调用restart***************************

●进程切换-----------------------------------------------------

1.2程序目录

下面是我们程序目录ps中的子目录结构及文件的功用。

tree

.

├──a.img(FAT12软盘映像:

将复制进文件LOADER.BIN和KERNEL.BIN)

├──boot(引导&装入)

│  ├──boot.asm(引导扇区:

FAT12、装入LOADER.BIN)

│  ├──include(包含汇编程序)

│  │  ├──fat12hdr.inc(FAT12的常量定义)

│  │  ├──load.inc(装载地址的常量定义)

│  │  └──pm.inc(保护模式的常量与宏定义)

│  └──loader.asm(装载程序:

获取并显示内存信息、定义并初始化GDT、

├──include(包含头文件)进入保护模式、启动分页机制、加载kernel)

│  ├──const.h(定义类型和常量)

│  ├──global.h(定义全局数据结构[数组])

│  ├──proc.h(定义进程表和任务结构)

│  ├──protect.h(定义保护模式下的数据结构类型和符号常量)

│  ├──proto.h(定义函数的原型)

│  ├──sconst.inc(定义汇编程序用的PCB、时钟控制器常量和选择符常量)

│  ├──string.h(定义memcpy和memset的函数原型)

│  └──type.h(定义无符号整数和函数指针类型)

├──kernel(内核程序)

│  ├──clock.c(定义时钟中断处理程序clock_handler)

│  ├──global.c(定义全局数据结构[数组])

│  ├──i8259.c(初始化时钟控制器)

│  ├──kernel.asm(切换GDT、装入IDT和TTS、调用main.c中的kerel_main()、

│  │  定义异常和硬件中断处理、定义save和restart函数)

│  ├──main.c(初始化进程表、定义用户进程函数)

│  ├──protect.c(定义异常与硬件中断处理、初始化TSS和LDT描述符)

│  └──start.c(复制GDT、初始化IDT)

├──lib(库函数)

│  ├──kliba.asm(定义显示串、端口I/O和开闭硬件中断的汇编函数)

│  ├──klib.c(定义整数转字符串、显示整数和延时函数)

│  └──string.asm(定义内存复制、内存设置和串复制函数)

└──Makefile(定义用于自动编译和软盘挂载/文件复制的Make文件)

1.3逻辑框图

与实模式下进程调度的类似。

1.4运行结果

2程序模块

boot.asm与我们的boot5.asm相同,loader.asm及其3个包含文件fat12hdr.inc、load.inc和pm.inc与上次实验中的相同,没有必要重复介绍。

下面只是关于内核程序诸模块的功能介绍与代码分析。

2.1应用程序函数

为了简单,我们在内核程序组中增加了C程序main.c,在其中初始化进程表,并定义3个函数TestA、TestB、TestC来充当3个用户进程。

2.1.1进程函数TestX

这些进程函数很简单,只是显示字符串“A”/“B”/“C”+计数+句点的死循环。

下面它们的C语言源代码(main.c):

/*===========================================================*

TestA

*===========================================================*/

voidTestA()

{

inti=0;

while

(1){

disp_str("A");

disp_int(i++);

disp_str(".");

delay

(1);

}

}

/*===========================================================*

TestB

*===========================================================*/

voidTestB()

{

inti=0x1000;

while

(1){

disp_str("B");

disp_int(i++);

disp_str(".");

delay

(1);

}

}

/*===========================================================*

TestC

*===========================================================*/

voidTestC()

{

inti=0x2000;

while

(1){

disp_str("C");

disp_int(i++);

disp_str(".");

delay

(1);

}

}

2.1.2串显示函数disp_str

进程函数中的字符串显示函数disp_str被定义在汇编库程序kliba.asm(也与上次实验的相同)中:

;=============================================================

;voiddisp_str(char*info);

;=============================================================

disp_str:

pushebp

movebp,esp

movesi,[ebp+8];pszInfo

movedi,[disp_pos]

movah,0Fh

.1:

lodsb;ds:

esi->al

testal,al

jz.2

cmpal,0Ah;是回车吗?

jnz.3

pusheax

moveax,edi

movbl,160

divbl

andeax,0FFh

inceax

movbl,160

mulbl

movedi,eax

popeax

jmp.1

.3:

mov[gs:

edi],ax

addedi,2

jmp.1

.2:

mov[disp_pos],edi

popebp

ret

该函数通过改写显存内容来显示字符(绿色代码)。

在此函数中字符串被显示在由全局变量disp_pos所指定的位置,显示完后再更新该变量的值(红色代码)。

如果显示的字符是回车符,则让EAX=EDI(=disp_pos),EAX/160=AL,EDI=(AL++)*160为下一行的首地址(蓝色代码)。

因每行80列,每个字符位占两个字节(AL=字符、AH=颜色),所以一行为160B。

2.1.3延时函数delay

延时函数delay则被定义在C库程序klib.c中,它是一个三层循环,最外层的循环是函数的输入参数,在我们的程序中取为1:

/*===========================================================*

delay

*===========================================================*/

PUBLICvoiddelay(inttimes)

{

inti,j,k;

for(k=0;k

for(i=0;i<10;i++){

for(j=0;j<10000;j++){}

}

}

}

2.2入口函数

内核的入口在kernel.asm的_start函数(与上次实验的5.1中的代码相似,红色代码为不同的部分)中:

_start:

;把esp从LOADER挪到KERNEL

movesp,StackTop;堆栈在bss段中

movdword[disp_pos],0

sgdt[gdt_ptr];cstart()中将会用到gdt_ptr

callcstart;在此函数中改变了gdt_ptr,让它指向新的GDT

lgdt[gdt_ptr];使用新的GDT

lidt[idt_ptr]

jmpSELECTOR_KERNEL_CS:

csinit

csinit:

;“这个跳转指令强制使用刚刚初始化的结构”

xoreax,eax

movax,SELECTOR_TSS

ltrax

jmpkernel_main

这段代码所完成的工作有:

●更新堆栈指针ESP=StackTop(跳转到kernel时已经切换了SS)

●初始化disp_pos=0

●切换GDT:

保存老GDTR、调用cstar(复制GDT、初始化IDT)、装入新GDT

●装入IDT和TSS

●跳转到main.c中的kerel_main()函数来初始化进程表、设置时钟中断处理程序、打开时钟中断、调用restart函数

在汇编程序kernel.asm中还

展开阅读全文
相关资源
猜你喜欢
相关搜索
资源标签

当前位置:首页 > 医药卫生 > 基础医学

copyright@ 2008-2022 冰豆网网站版权所有

经营许可证编号:鄂ICP备2022015515号-1