BUAAOS——Lab1实验报告
lab1实验报告
实验思考题
1.1
也许你会发现我们的readelf程序是不能解析之前⽣成的内核⽂件(内核⽂件是可执⾏⽂件)的,⽽我们之后将要介绍的⼯具readelf则可以解析,这是为什么呢?(提⽰:尝试使⽤readelf -h,观察不同)
通过linux内置的readelf⼯具即使⽤readelf -h命令⾏分别对testELF⽂件和之前⽣成的内核⽂件vmlinux的elf⽂件头进⾏查看:
可以很清楚的看出,之前⽣成的vmlinux内核⽂件为⼤端存储,⽽testELF为⼩端存储。
时过境迁因此我们⾃⼰编写的readelf程序只能解析testELF⽽不能解析vmlinux内核⽂件,因为编写readelf程序使⽤c语⾔不能简单的读取⼤端存储的数据。
1.2
内核⼊⼝在什么地⽅?main 函数在什么地⽅?我们是怎么让内核进⼊到想要的 main 函数的呢?⼜是怎么进⾏跨⽂件调⽤函数的呢?
杨桃产地内核的⼊⼝的起始地址为0x80000000,main函数在0x80010000。
在⼊⼝函数本实验为start.S内部使⽤跳转指令jal跳转到指定的函数地址。跨⽂件调⽤函数通过跳转指令来调⽤,同时在跳转之前需要将数据存
⼊栈中。
实验难点图⽰
本次课下实验的难点其实就是能否读懂现有代码以及学习如何调⽤现有的⼯具。
例如在编写readelf.c⽂件中,我们可以从ELF⼿册中得知每个elf⽂件头结构体的结构,以及它内部的数据,随后根据适当的处理得出每个Section的结构体,再从其中获取所需要的数据。
即思路可以概括为⼀下步骤:
夆怎么读
知道结构体中的数据
typedef struct {
unsigned char e_ident[EI_NIDENT]; /* Magic number and other info */
// 存放魔数以及其他信息
Elf32_Half e_type; /* Object file type */
食品安全知识培训内容// ⽂件类型
Elf32_Half e_machine; /* Architecture */
// 机器架构
Elf32_Word e_version; /* Object file version */
// ⽂件版本
Elf32_Addr e_entry; /* Entry point virtual address */
/
/ ⼊⼝点的虚拟地址
Elf32_Off e_phoff; /* Program header table file offt */
// 程序头表所在处与此⽂件头的偏移
Elf32_Off e_shoff; /* Section header table file offt */
// 段头表所在处与此⽂件头的偏移
Elf32_Word e_flags; /* Processor-specific flags */
// 针对处理器的标记
Elf32_Half e_ehsize; /* ELF header size in bytes */
形容时间过得快的句子// ELF⽂件头的⼤⼩(单位为字节)
种花赚钱Elf32_Half e_phentsize; /* Program header table entry size */
// 程序头表⼊⼝⼤⼩
Elf32_Half e_phnum; /* Program header table entry count */
// 程序头表⼊⼝数
Elf32_Half e_shentsize; /* Section header table entry size */
// 段头表⼊⼝⼤⼩
Elf32_Half e_shnum; /* Section header table entry count */
// 段头表⼊⼝数
Elf32_Half e_shstrndx; /* Section header string table index */
// 段头字符串编号
} Elf32_Ehdr;
了解readelf.c⽂件中已有代码如何获取结构体中的数据
仿照已有代码获取所需要的数据:e_shoff、e_shentsize、e_shnum
再例如补全print.c⽂件中的代码,需要的也是这种思路:
了解已有的specifier的处理过程
查看已有的printNum、printChar等⽅法
获取所需要的各种参数
怎么泡腐竹出差的拼音仿照已有的specifier的处理过程,对d、D进⾏处理
同时需要充分熟悉有关C语⾔指针的知识
⽽对于更多的细节,对于本次实验练习关系并不是很⼤,只需要⼤致了解内核启动和编译链接的过程。但是,为了更好的理解和熟悉相关的步骤,需要仔细阅读每⼀部分的代码,了解每部分代码所充当的⾓⾊和内容。
体会与感想
最⼤的体会就是,操作系统这⼀门课,与其说是理解软硬件之间是如何进⾏交互的,不如说是C语⾔与汇编的从⼊门到精通到再精通。
因为c语⾔代码随处可见,许多指针以及结构体调⽤和传递是穿插在整个操作系统的。
操作系统的启动规则很复杂且重要。⼀种操作系统不只是也不可能只属于⼀台机器的,为了可移植性,需要对操作系统的各个⾏为都进⾏严格的规范,启动这⼀步骤同样,内存分配、加载内核等⾏为拥有很庞⼤的规则,⽽了解和熟知这些规则需要耗费⼤量的时间和经理。同时我也感叹到这些规则的逻辑严谨并且⾮常清晰,是许多次不断探索的结果。
按照已有的规定去编写代码,既简单⼜⿇烦。简单是因为你不需要去思考规范问题,⿇烦是规则并不符合⾃⼰的编程习惯,因此需要花更多精⼒去适应这种过程。