项目设计1
一、项目设计目的
- 熟悉ELF文件格式,了解GeekOS系统如何将ELF格式的可执行程序装入到内存,建立内核进程并运行的实现技术。
二、项目设计要求
- 1、修改project1/src/geekos/elf.c文件:在函数Parse_ELF_Executable( )中添加代码,分析ELF格式的可执行文件(包括分析得出ELF文件头、程序头,获取可执行文件长度,代码段、数据段等信息),并填充Exe_Format数据结构中的域值。
- 2、修改/project1/src/geekos/lprog.c 文件中的 Spawn_Program()函数,将其中的 virtSize 局部变量修改为静态全局变量,即在文件头部添加“static unsigned long virtSize;”一行代码。
- 3、修改 lprog.c 文件中的 Printrap_Handler()函数
- 4、在Linux环境下编译系统得到GeekOS镜像文件。终端进入project1的build目录下make depend、make。
- 5、编写一个相应的bochs配置文件。进入project1的 Build目录下输入gedit .bochsrc编写bochs配置文件。
- 6、在bochs中运行GeekOS系统显示结果。进入project1的 Build目录下输入bochs运行Bochs模拟器,执行GeekOS内核。
三、步骤
1、修改project1/src/geekos/elf.c文件
1.1 在函数Parse_ELF_Executable( )中添加以下代码
//TODO("Parse an ELF executable image");
//利用ELF头部结构体指向可执行文件头部,便于获取相关信息
elfHeader *ehdr = (elfHeader*)exeFileData;
//段的个数
exeFormat->numSegments = ehdr->phnum;
//代码入口地址
exeFormat->entryAddr = ehdr->entry;
//获取头部表在文件中的位置,便于读取信息
programHeader *phdr = (programHeader*)(exeFileData + ehdr->phoff);
//填充Exe_Segment
unsigned int i;
for(i = 0; i < exeFormat->numSegments; i++, phdr++)
{
struct Exe_Segment *segment = &exeFormat->segmentList[i];
//获取该段在文件中的偏移量*
segment->offsetInFile = phdr->offset;
//获取该段的数据在文件中的长度
segment->lengthInFile = phdr->fileSize;
//获取该段在用户内存中的起始地址
segment->startAddress = phdr->vaddr;
//获取该段在内存中的大小
segment->sizeInMemory = phdr->memSize;
//获取该段的保护标志位
segment->protFlags = phdr->flags;
}
return 0;
2、修改/project1/src/geekos/lprog.c 文件中的 Spawn_Program()函数
- 注释掉Spawn_Program()函数的//unsigned long virtSize;
在开头加入static unsigned long virtSize;
3、修改 lprog.c 文件中的 Printrap_Handler()函数
static void Printrap_Handler( struct Interrupt_State* state )
{
char *msg;
/* 此处修改以下内容以正确显示 a.c 中的局部变量 */
if (state->eax <= virtSize)
msg = (char *)virtSpace + state->eax;
else
msg = (char *)state->eax;
print(msg);
g_needReschedule = true;
return;
}
4、运行
5、编写bochs配置文件
将 .bochsrc 的内容改为以下代码:
megs: 8
boot: a
floppya: 1_44=fd.img, status=inserted
log: ./bochs.out
ata0-master: type=disk, path=diskc.img, mode=flat, cylinders=40, heads=8, spt=64
6、运行bochs
四、作业题
1、ELF文件格式包括什么内容?
- 答:ELF文件由4部分组成,分别是ELF头(ELF header)、程序头部表(Program header table)、节区(Section)和节头部表(Section header table)。
2、如何由ELF文件建立一个可运行的进程单位?
- 答:ELF文件是保存在GeekOS的PFAT文件系统中,首先需要将文件读入内存缓冲区,解析程序段和数据段等将其装入内存,之后建立进程执行装入内存相应的代码。
3、在GeekOS系统中建立一个内核级线程应该建立什么相应实体单元?
- 在GeekOS系统中建立一个内核级线程应该建立什么相应实体单元?
4、在GeekOS系统内核中,如何运行建立好的线程?
- 答:GeekOS操作系统为不同状态下的进程准备了不同的进程队列:就绪队列s_runQueue,等待队列s_reaperWaitQueue,销毁队列s_graveyardQueue,而运行态的只有一个g_currentThread指针指向哪个进程哪个进程就处于运行态。系统启动之后,会从Entry入口执行Main函数,执行到Init_Scheduler()函数时会建立3个最开始的进程Main、Idle和Reaper,同时调度Main。Idle在就绪队列队尾,当无进程可调度时Idle就会被调度并一直运行Yield()函数检查是否有可调度进程并让步。所以新建的线程加入到就绪队列就可以通过相应的调度算法被调度运行。