南京大学计算机系统实验报告,南京大学 计算机系统基础 课程实验 2018(PA3)

其他部分:

这一部分应该算是最简单的一部分了,几乎就是按照文档的做就可以了,但是有几个问题值的关注

一个系统调用的生命周期是什么

使用navy-apps/tests/hello作为例子分析

从printf会调用klib中间的printf 函数,至于为什么不是调用Nemu中间实现的或者系统的printf以后会讲到。

printf("Hello World from Navy-apps for the %dth time!\n", i ++);

klib中间经过反复调用各种函数,最终会到达nano.c中间。这里大家就把klib当做一个黑盒子,我看一下其中的代码,说实话,有一种读天书的感觉。

nano.c 中间定义了大量的系统调用其中就包括需要使用_write

int _write(int fd, void *buf, size_t count){

return _syscall_(SYS_write, fd, (intptr_t)buf, count);

}

nano.c 中间封装了syscall的调用原理,也就是使用0x80号中断

intptr_t _syscall_(int type, intptr_t a0, intptr_t a1, intptr_t a2) {

int ret = -1;

asm volatile("int $0x80" : "=a"(ret) : "a"(type), "b"(a0), "c"(a1), "d"(a2));

return ret;

}

system.c 定义在Nemu模块中间,包含有int的处理函数

make_EHelper(int) {

uint8_t int_NO = id_dest->val;

raise_intr(int_NO, *eip);

print_asm("int %s", id_dest->str);

}

intr.c 中间定义raise_intr函数读取CPU的中断向量表的入口地址,并且开始执行函数,目前raise_intr函数只会被int调用,在PA4中间还可以被时钟中断调用的。

void raise_intr(uint8_t NO, vaddr_t ret_addr) {

rtl_push(&cpu.eflags);

cpu.IF = 0; // assume we forbit every all IF in the interrupt

rtl_push(&cpu.cs);

rtl_push(&ret_addr); // eip

uint32_t a = vaddr_read(idtr_addr + sizeof(GateDesc) * NO, 4);

uint32_t b = vaddr_read(idtr_addr + sizeof(GateDesc) * NO + 4, 4);

uint32_t entry_addr = (a & 0xffff) | (b & 0xffff0000);

rtl_j(entry_addr);

}

cte.c中间_cte_init函数实现创建了各种终端号的入口地址,都是使用函数的形式定义的。

trap.S中间定义了函数入口,并且在asm_trap函数中间写下一些列的汇编,其中有一个非常关键的操作。调用函数之前push,根据i386的函数调用规则,push的内容就是参数,也就是esp作为参数传入到一个irq_handle的函数中间了。

pushl %esp

call irq_handle

cte.c 中间定义了irq_handle函数,该函数的参数竟然是Context *, 上一步中间说明了esp是参数,也就是调用irq_handle之前的一系列的push的操作就是构成了Context的的内容了。irq_handle 函数会调用一个函数指针,该函数指针指向的内容随架构变化,在x86-neum的架构下会指向do_event函数

irq.c中间定义了do_event函数,进一步调用do_syscall函数

syscall.c 中间定义syscall.c函数

fs.c 中间定义了fs_write函数来处理所有的读写操作,由于虚拟文件的封装,wiret函数会调用实现注册好的serial_write函数。

13.device.c中间包含了seraial_write函数就很简单了,_put()的输出就可以了

清楚了上面过程,整个PA3大概就可以做完了,中间可能会遇到各种bug, 只是需要一层一层的函数调用检查就可以了。

brk 的含义是什么

Nemu和AM是如何协同合作的

printf到底是谁的

随着试验的进行,大家逐渐会模糊一件事情,当你想要调试的时候,printf到底glibc提供的(也就是物理机上安装的操作系统上的运行时库提供的),还是klib提供的(就是哪一个嵌入式库提供的),还是Nemu中间的printf(就是PA2在Nemu中间实现的一系列的io函数)。当然其中使用Log函数是如何实现的。

  • 0
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值