Greekos操作系统实验.docx

上传人:b****3 文档编号:4890021 上传时间:2022-12-11 格式:DOCX 页数:27 大小:102.30KB
下载 相关 举报
Greekos操作系统实验.docx_第1页
第1页 / 共27页
Greekos操作系统实验.docx_第2页
第2页 / 共27页
Greekos操作系统实验.docx_第3页
第3页 / 共27页
Greekos操作系统实验.docx_第4页
第4页 / 共27页
Greekos操作系统实验.docx_第5页
第5页 / 共27页
点击查看更多>>
下载资源
资源描述

Greekos操作系统实验.docx

《Greekos操作系统实验.docx》由会员分享,可在线阅读,更多相关《Greekos操作系统实验.docx(27页珍藏版)》请在冰豆网上搜索。

Greekos操作系统实验.docx

Greekos操作系统实验

操作系统实验报告

目录

1.实验目的1

2.开发环境的搭建2

2.1在虚拟机上安装Linux2

2.2安装VMwareTools和实现文件共享2

2.3BochsPC模拟器的安装2

3.项目具体实现2

3.1项目02

3.1.1项目设计要求3

3.1.2项目设计原理3

3.1.3项目设计的具体实现4

3.1.4系统编译运行的原理及结果5

3.2项目16

3.2.1项目设计要求6

3.2.2项目设计原理6

3.2.3项目设计的具体实现7

3.2.4系统编译运行的原理及结果9

3.3项目210

3.3.1项目设计要求10

3.3.2项目设计原理10

3.3.3项目设计的具体实现11

3.3.4系统编译运行的原理及结果18

4.遇到的问题及解决办法19

5.实验总结19

 

1.实验目的

操作系统是管理系统软件,硬件资源,控制程序运行,改善人机界面及交互,提供各种服务,合理组织计算机工作流程和为用户有效地使用计算机提供良好运行环境的系统软件,它为用户使用计算机提供了一个方便,灵活,安全,可靠的工作环境,它也是其他运用软件赖以存在的基础。

操作系统是计算机科学与技术专业核心的课程,涉及到很多方面的知识,概念和原理抽象。

在课程学习过程中,主要是学习理论知识,而操作系统实验则从理论转向实践,让我们亲自去编写一个操作系统内核,从而可以更加深入的理解操作系统软件的实现过程,增强了实践动手能力。

本实验主要要求我们熟悉GeekOs的项目编译、调试和运行环境,掌握GeekOs运行工作过程。

熟悉ELF文件格式,了解GeekOs系统如何将ELF格式的用户可执行程序装入到内存,建立内核线程并运行的实现技术。

扩充GeekOs操作系统内核,使得系统能过支持用户级进程的动态创建和执行。

2.开发环境的搭建

在实现这个过程中。

由于Geekos是开源的基于linux系统开发的操作系统,我们需要用到linux下的编译环境。

所以需要搭建linux环境。

为了实现与Windows下的文件进行共享,需要安装VMwareTools软件包。

在运行的时候需要bochspc模拟器来模拟操作系统,所以也需要安装bochspc模拟器。

2.1在虚拟机上安装Linux

本次环境的搭建是采用在Windows环境下先安装一个PC虚拟机,然后在虚拟机上安装Linux操作系统。

本次实验选择安装的虚拟机软件VMware,安装过程则为首先在相应的网站下载此安装软件,然后其根据提示安装。

安装完成后就会在桌面上显示一个虚拟机图标VMware-workstation。

VMware安装完成后,可以开始建立虚拟机,每新建一个虚拟机都会要求建立一个配置文件,这个配置文件相当于电脑中的硬件配置表,用户可以在配置文件中决定虚拟机的硬盘如何配置,内在多大,准备运行哪种操作系统,是否有网络等。

其中中安装的过程中要选取实验需要的相应组件进行安装,其中本次实验必须需要的组件是:

AWK、Diff3、Egrep、gcc、GNUbinutils、GNUMake、Perl、NASM。

2.2安装VMwareTools

在虚拟机上安装VMwareTools,就相当于给Linux安装各种驱动程序。

此步的主要目的就是为了以后的工程运行时能够实现与Windows下的文件进行共享,因为bochsPC模拟器要在Windows下运行,所以这里的文件就只能通过这一步的共享,从而达到在Linux下工程运行后得到的build下的镜像文件替代源文件,从而使得bochsPC模拟器能够得到所需的镜像文件。

2.3安装BochsPC模拟器

BochsPC模拟器:

用来运行GeekOS系统。

安装此软件只需设定好想安装到的文件目录后一直点下一步就可以安装成功。

最后设置bochsrc.txt文件。

根据实验的需要,一般只需要修改以下几项:

(1)vgaromimage:

$BXSHARE/VGABIOS-lgpl-latest

(2)romimage:

file=$BXSHARE/BIOS-bochs-latest,address=0xf0000

(3)floppya:

1_44=fdx.img,status=insertedboot:

floppy

(4)做Project1的时候,需要添加一个磁盘镜像

ata0-master:

type=disk,mode=flat,path=diskx.img,cylinders=615,heads=6,spt=17配置完bochsrc.txt以后,而且有了从工程生成的操作系统Geekos就可以用bochs软件模拟了。

到bochs的安装目录下,输入bochs命令,选择6开始模拟。

如果你的操作系统编译成功,就可以得到想要的结果。

3.项目具体实现

3.1项目0

本项目主要目的是要熟悉GeekOS的项目编译、调试和运行环境,掌握GeekOS运行工作过程。

3.1.1项目设计要求

(1)搭建GeekOS的编译和调试平台,掌握GeekOS的内核进程工作原理。

(2)熟悉键盘操作函数,编程实现一个内核进程。

该进程的功能是:

接收键盘输入的字符并显示到屏幕上,当输入Ctrl+D时,结、束进程的运行。

3.1.2项目设计原理

在这个项目里面主要了解两部分的内容:

内核线程和键盘处理,相应的文件是thread.c和keyboard.c。

Geekos系统的默认内核只支持内核态的线程,在系统初始化的时候,main函数分别执行了4个内核函数,一个内核函数负责软驱中断,一个复杂键盘中断,还有两个负责进程调度。

函数Start_Kernel_Thread()其可以生成一个内核线程:

1.内核线程结构的定义如下:

structKernel_Thread{

unsignedlongesp;

volatileunsignedlongnumTicks;

intpriority;

DEFINE_LINK(Thread_Queue,Kernel_Thread);

void*stackPage;

structUser_Context*userContext;

structKernel_Thread*owner;

intrefCount;

Booleanalive;

structMutexjoinLock;

structConditionjoinCond;

};

esp字段用来存放一个线程挂起的堆栈指针;

stackPage字段指向内核线程的堆栈页面

numTicks和priority分别被调度程序用来实现基于先占权和基于优先权的时间片调度。

DEFINE_LINK宏定义一个内核线程在线程队列上时的前一个和后一个字段。

userContext字段如果不为空,则指向一个线程用户环境,它是一个允许线程执行用户模式的代码和数据的组合段。

内核线程有两种方式创建。

在内核里独立运行的线程可通过Start_Kernel_Thread()函数来创建,该函数通过一个指针指向一个执行线程体的启动函数。

线程所执行的用户模式的程序由Start_User_Thread()函数创建,并且用一指针指向一个用户环境和用户环境内存中代码入口点的地址。

调用Exit()函数销毁内核线程。

入口参数分别为:

函数地址,函数参数(无参数就写0),优先级设定,线程属性(false为内核线程,true为用户线程),返回值Mythread的数据类型是staticstructKernel_Thread*thread

2.Start_Kernel_Thread完成的工作:

Create_Thread(priority,detached)//根据优先级创建一条线程

kthread=Alloc_Page()//为线程分配内存空间

stackPage=Alloc_Page()

Init_Thread(kthread,stackPage,priority,detached)

Add_To_Back_Of_All_Thread_List(&s_allThreadList,kthread)

Setup_Kernel_Thread(kthread,startFunc,arg)//配置内核线程的初始化

Make_Runnable_Atomic(kthread);//设置线程运行的原子性操作

Disable_Interrupts();//禁止中断

Make_Runnable(kthread);//线程运行

Enable_Interrupts();//使能中断

3.Geekos处理键盘代码

在keyboard.c里面提供了一个功用函数KeycodeWait_For_Key(void),循环等待一个键盘事件,然后返回一个16位的数据Keycode型的,在keyboard.h里定义了所有的键盘代码。

Read_Key(Keycode*keycode)函数可以处理队列键盘按键,可以保存到队列中并输出。

关于Keycode的定义是:

低8位用来表示键盘值,通过s_scanTableNoShift和s_scanTableWithShift这两个数组来转换相应的键盘码为所表示字符的ASCII码,高六位分别是:

KEY_SPECIAL_FLAG(特殊键,比如F1,F2)用返回的值key&0x0100就可以判断是否按下特殊健,1为有效,说明是特殊健,0则不是,以下的几种情况类似

KEY_KEYPAD_FLAG(小键盘键)0x0200

KEY_SHIFT_FLAG(左,右SHIFT)0x1000

KEY_ALT_FLAG(左,右ALT)0x2000

KEY_CTRL_FLAG(左,右CTRL)0x4000

KEY_RELEASE_FLAG(键弹起来标志位)0x8000

3.1.3项目设计的具体实现

projcet0项目主要是对main.c文件中的键盘相应的实现。

我们创建函数keyboard()。

下面是具体的代码。

voidkeyboard(ulong_targ)

{

Keycodekey;

Print("PleaseEnterthecharacters.press'Ctrl+d'toexit\n\n");

while(true)

{

Set_Current_Attr(ATTRIB(BLACK,RED|BRIGHT));

key=Wait_For_Key();

if(key==(KEY_CTRL_FLAG+'d'))

{

Print("\n\nKeyEnd\n");

break;

}

if(!

(key&KEY_RELEASE_FLAG)&&!

(key&KEY_SPECIAL_FLAG))

{

Print("%c",key);

}

}

}

 

voidMain(structBoot_Info*bootInfo)

{

Init_BSS();

Init_Screen();

Init_Mem(bootInfo);

Init_CRC32();

Init_TSS();

Init_Interrupts();

Init_Scheduler();

Init_Traps();

Init_Timer();

Init_Keyboard();

Set_Current_Attr(ATTRIB(BLACK,GREEN|BRIGHT));

Print("\n\nWelcometosutingting'sGeekOS!

\n\n");

Start_Kernel_Thread(keyboard,0,5,1);

Set_Current_Attr(ATTRIB(BLACK,GRAY));

TODO("Startakernelthreadtoechopressedkeysandprintcounts");

Exit(0);

}

3.1.4系统编译运行的原理及结果

I.编译源代码

在linux的终端中:

(1)输入:

cd+空格+路径(project0文件下的build文件所在的路径)

(2)终端进入build目录

$makedepend

$make

如果没有问题就会自动生成一个镜像文件fd.img。

II修改bochsrc.txt配置文件

其具体的文件bochsrc.txt内容如下:

#配置模拟器的BIOS和显示系统的BIOS文件

vgaromimage:

$BXSHARE/VGABIOS-lgpl-latest

romimage:

file=$BXSHARE/BIOS-bochs-latest,address=0xf0000

#配置模拟器内存大小

megs:

8

#配置模拟器从软盘引导系统

boot:

a

#这是对模拟器硬盘的描述,其中disk.img是硬盘的映像文件,将其注释掉,因为项目0

#不需要硬盘。

#软盘A的描述,其中fd.img为软盘映像文件

floppya:

1_44=fd.img,status=inserted

#floppya:

1_44=fd_aug.img,status=inserted

#这是配置模拟器的系统文件

keyboard_serial_delay:

200

floppy_command_delay:

500

vga_update_interval:

300000

ips:

1000000

mouse:

enabled=0

private_colormap:

enabled=0

i440fxsupport:

enabled=0

#配置模拟器的日志文件

log:

./bochs.out

III.运行bochs

终端运行bochs选择6即的运行结果如下图1所示:

图1project0的运行结果

3.2项目1

本项目主要是为了让学生熟悉ELF文件格式,了解Geekos系统如何将ELF 格式的用户可执行程式装入到内存,建立内核进程并运行的实现技术。

3.2.1项目设计要求

分析ELF格式的可执行文件(包括分析得出ELF文件头、程序头,获取可执行文件的长度,代码段、数据段等信息),并填充Exe_Format数据结构中的域值。

(1)修改/geekos/elf.c文件:

在函数Parse_ELF_Executable()中添加代码,分析ELF格式的可执行文件(包括分析得出ELF文件头、程序头,获取可执行文件长度,代码段、数据段等信息),并填充Exe_Format数据结构中的域值。

(2)在Linux环境下编译系统得到GeekOS镜像文件。

(3)编写一个相应的bochs配置文件。

(4)在bochs中运行GeekOS系统显示结果。

3.2.2项目设计原理

项目的主要内容是在文件elf.c中函数Parse_ELF_Executable()添加代码,实现对ELF文件的解释,装入到内存运行,得到指定的结果.主要是分析ELF文件。

为以后的工程执行应用程序做准备,需要理解的是ELF的一下原理性。

需要关注以下几个数据结构:

具体代码在\project1include\geekos\elf.h中:

typedefstruct{

unsignedcharident[16];

unsignedshorttype;

unsignedshortmachine;

unsignedintversion;

unsignedintentry;

unsignedintphoff;//programheader偏移量

unsignedintsphoff;//sectionheader的偏移

unsignedintflags;//指示具体的进程

unsignedshortehsize;//elf头部的大小

unsignedshortphentsize;//programheader的大小

unsignedshortphnum;//programheader的个数

unsignedshortshentsize;

unsignedshortshnum;

unsignedshortshstrndx;

}elfHeader;

structExe_Format{

structExe_SegmentsegmentList[EXE_MAX_SEGMENTS];//段的定义

intnumSegments;//可执行文件中段的个数

ulong_tentryAddr;//代码入口

};

structExe_Segment{

ulong_toffsetInFile;//段在可执行文件中的偏移

ulong_tlengthInFile;//段在可执行文件中的长度

ulong_tstartAddress;//段在内存中的起始地址

ulong_tsizeInMemory;//段在内存中的大小

intprotFlags;//VM保护标志

};

typedefstruct{

unsignedinttype;

unsignedintoffset;

unsignedintvaddr;

unsignedintpaddr;

unsignedintfileSize;

unsignedintmemSize;

unsignedintflags;

unsignedintalignment;

}programHeader;

offset表示该成员给出了该段的驻留位置相对于文件开始处的偏移。

fileSize表示该成员给出了文件映像中该段的字节数;它可能是0。

memSize表示该成员给出了内存映像中该段的字节数;它可能是0。

vaddr表示该成员给出了该段在内存中的首字节地址。

flags表示该成员给出了和该段相关的标志。

这是编程实现过程主要部分,对linux下ELF有一定了解之后,就能顺利的完成工程1.

3.2.3项目设计的具体实现

下面是project1\src\geekos下的elf.c中的代码。

#include

#include

#include

#include/*fordebugPrint()statements*/

#include

#include

#include

#include

intParse_ELF_Executable(char*exeFileData,ulong_texeFileLength,

structExe_Format*exeFormat)

{

inti;

elfHeader*head=(elfHeader*)exeFileData;

programHeader*proHeader=(programHeader*)(exeFileData+head->phoff);

Set_Current_Attr(ATTRIB(BLACK,BLUE|BRIGHT));

Print("ident=%s,",head->ident);

Print("type=%d,",head->type);

Print("machine=%d,",head->machine);

Print("version=%d\n",head->version);

Print("entry=%d,",head->entry);

Print("phoff=%d,",head->phoff);

Print("sphoff=%d,",head->sphoff);

Print("flags=%d\n",head->flags);

Print("ehsize=%d,",head->ehsize);

Print("phentsize=%d,",head->phentsize);

Print("phnum=%d,",head->phnum);

Print("shentsize=%d\n",head->shentsize);

Print("shnum=%d,",head->shnum);

Print("shstrndx=%d\n",head->shstrndx);

Set_Current_Attr(ATTRIB(BLACK,RED|BRIGHT));

Print("type=%d,",proHeader->type);

Print("offset=%d,",proHeader->offset);

Print("vaddr=%d,",proHeader->vaddr);

Print("paddr=%d\n",proHeader->paddr);

Print("fileSize=%d,",proHeader->fileSize);

Print("memSize=%d,",proHeader->memSize);

Print("flags=%d,",proHeader->flags);

Print("alignment=%d\n",proHeader->alignment);

Set_Current_Attr(ATTRIB(BLACK,GREEN|BRIGHT));

for(i=0;iphnum;i++)//programheadertablenumber

{

exeFormat->segmentList[i].offsetInFile=proHeader->offset;

exeFormat->segmentList[i].lengthInFile=proHeader->fileSize;

exeFormat->segmentList[i].startAddress=proHeader->vaddr;

exeFormat->segmentList[i].sizeInMemory=proHeader->memSize;

exeFormat->segmentList[i].protFlags=proHeader->flags;

proHeader++;

}

exeFormat->numSegments=head->phnum;

exeFormat->entryAddr=head->entry;

return0;

}

3.2.4系统编译运行的原理及结果

I.编译源代码

在linux的终端中:

(1)输入:

cd+空格+路径(project1文件下的build文

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

当前位置:首页 > 法律文书 > 调解书

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

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