09保护模式下的进程调度.docx
- 文档编号:2434986
- 上传时间:2022-10-29
- 格式:DOCX
- 页数:39
- 大小:2.39MB
09保护模式下的进程调度.docx
《09保护模式下的进程调度.docx》由会员分享,可在线阅读,更多相关《09保护模式下的进程调度.docx(39页珍藏版)》请在冰豆网上搜索。
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中还 ●
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- 09 保护 模式 进程 调度