1、1西北工业大学 操作系统实验 实验报告一、实验目的熟悉可执行链接文件(ELF)的结构,了解 GeekOS 将 ELF 格式的可执行程序加载到内存,建立内核线程并运行的实现技术。二、实验要求1.修改 Project1 项目中的/GeekOS/elf.c 文件:在函数 Parse_ELF_Executable()中添加代码,分析 ELF 格式的可执行文件(包括分析得出 ELF 文件头、程序头) ,获取可执行文件长度、代码段、数据段等信息,并打印输出。并且,填充Exe_Format 数据结构中的值域。2.掌握 GeekOS 在核心态运行可执行程序的原理,绘制出可执行程序在内核中加载、运行的流程图(需
2、反映关键函数的调用关系) 。3.回答实验讲义 P125 页的思考题。三、实验过程及结果1、修改 Project1 项目中的 /GeekOS/elf.c 文件:在函数 Parse_ELF_Executable()中添加代码,分析 ELF 格式的可执行文件(包括分析得出 ELF 文件头、程序头) ,获取可执行文件长度、代码段、数据段等信息,并打印输出。并且,填充Exe_Format 数据结构中的值域。答:修改 Project1 项目中的 /GeekOS/elf.c 文件:在函数Parse_ELF_Executable()中添加代码,如下:=elf.c=int Parse_ELF_Executabl
3、e(char *exeFileData, ulong_t exeFileLength, struct Exe_Format *exeFormat)int i;elfHeader *head=(elfHeader*)exeFileData;programHeader *proHeader=(programHeader *)(exeFileData+head-phoff);KASSERT(exeFileData!=NULL);KASSERT(exeFileLengthhead-ehsize+head-phentsize*head-phnum);KASSERT(head-entry%4=0);exe
4、Format-numSegments=head-phnum;2exeFormat-entryAddr=head-entry;for(i=0;iphnum;i+)exeFormat-segmentListi.offsetInFile=proHeader-offset;exeFormat-segmentListi.lengthInFile=proHeader-fileSize;exeFormat-segmentListi.startAddress=proHeader-vaddr;exeFormat-segmentListi.sizeInMemory=proHeader-memSize;exeFor
5、mat-segmentListi.protFlags=proHeader-flags;proHeader+;return 0;=elf.c=运行结果如图:2、掌握 GeekOS 在核心态运行可执行程序的原理,绘制出可执行程序在内核中加载、运行的流程图(需反映关键函数的调用关系) 。答:ELF(Executable and linking format)文件是 UNIX 系统实验室作为应用程序二进制接口而开发的可执行文件,是 x86 Linux 系统下的一种常用目标文件(object file)格式。ELF 文件格式如下表:ELF 文件在磁盘中的映象和在内存中的执行程序镜像的对应关系如下图:表
6、1 ELF 目标文件格式3连接程序视图 执行程序视图 ELF 头部 ELF 头部 程序头部表(可选) 程序头部表 节区 1 . 段 1 节区 n . 段 2 . . 节区头部表 节区头部表(可选) ELF 文件在磁盘中的映象和在内存中的执行程序镜像的对应关系如下图:ELFheaderCodeDatasectionheaderCodesectionheaderDataCodeoffsetDataoffsetD a t a s i z e C o d e s i z e CodeDataS t a c k ( 4 0 9 6 )E L F 文件镜像内存中执行镜像图 1 ELF 文件和内存中的可执行
7、文件镜像流程图如下:4四、实验分析思考题:输出个字符串为什么要如此大费周章?在 a.exe 中直接调用 Print函数是否可行?答:不可行,直接打印 Print(s1)则找不到字符串 s1 的正确位置,字符串变量名即代表地址信息,程序被加载进入内存时有了基址,需要通过基址加偏移量来找到字符串在内存中的正确位置,所以要调用 ELF_Print 函数。五、所遇问题及解决方法答:实验中遇到的问题首先就是代码难以阅读理解,对汇编陌生是一个主要的问题,其次就是代码之间的关联较多,层次较多,代码量也比较大,导致在阅读源码的过程中造成了很大的困难。最后在老师和同学们的帮助下,勉强理解了代码的基本结构以及实现的功能。通过此次实验,我由原来对操作系统只有一个粗浅的概念的认识的水平上升到对操作系统有比较深刻印象和理解的程度。不仅概念得到了进一步的理解,更对 geekos 在核心态下运行用户程序的原理有了更进一步的理解。