rCore Tutorial Chapter 1 练习

本文介绍了Linux下显示当前目录文件的C程序,展示了通过内联汇编获取调用栈信息的技巧,以及在RISC-V环境中使用QEMU模拟系统调用的示例。文章还探讨了应用程序占用的资源、内存空间分配、栈帧恢复方法,并讲解了如何通过GDB调试QEMU启动过程。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

这是 rCore Tutorial Book 第一章「应用程序与基本执行环境」的练习。

本文首发于 blog.skywt.cn,建议查看原文以获得更好的阅读体验。

课后练习

编程题

Program 1

1. 实现一个 linux 应用程序 A,显示当前目录下的文件名。

#include <dirent.h>
#include <stdio.h>

int main() {
   
    DIR *dir = opendir(".");
    struct dirent *entry;
    while ((entry = readdir(dir))) {
   
        printf("%s\n", entry->d_name);
    }
    return 0;
}

相关库的用法:

  • dirent.h 这个库中,定义了 DIR 数据类型,表示一个目录流。同时还定义了一个叫做 dirent 的数据类型,是一个结构体,其中一个成员是 char d_name[],即目录的名称。
  • opendir 函数打开一个目录流,返回的正是 DIR 对象。
  • readdir 函数以一个 DIR 对象为参数,返回一个 dirent 类型结构体,它表示传入的 DIR 指针指向的条目;同时,会将指针指向下一个条目。
Program 2

2. 实现一个 Linux 应用程序 B,能打印出调用栈链信息。

(前置知识:C 语言中内联汇编语句 asm 的用法)

这里在 x86_64 环境下运行。我们直接内联汇编命令,将栈底指针寄存器 rbp 取出来,并不断根据寄存器的内容追溯上一个栈帧的 rbp。(注意我们是 64 位环境,所以最好使用 64 位的 rbp 而不是 ebp)
需要注意的是,根据实践,第一个栈帧的 rbp 指向的是 0x1 而不是 0x0。while 循环何时停止需要根据此判断。
编写输出栈信息的函数如下:

void print_call_stack_info() {
   
    unsigned long long stack_ptr;
    asm ("mov %%rbp, %0" : "=r" (stack_ptr));

    printf("== BEGIN CALL STACK INFO\n");
    while (stack_ptr != 0x1) {
   
        printf(" == %p\n", (void*)stack_ptr);
        stack_ptr = *((unsigned long long*)stack_ptr);
    }
    printf("== END CALL STACK INFO\n");
}

递归调用的函数能让我们最直观地体会到栈的变化。编写好如上函数之后,我们来编写一个递归计算阶乘的函数,并让程序计算 5 的阶乘:

int fact(int x){
   
    printf("Calling fact(%d)\n", x);
    print_call_stack_info();
    if (x == 0) return 1;
    return fact(x-1) * x;
}

int main() {
   
    print_call_stack_info();
    printf("5! = %d\n", fact(5));
    return 0;
}

编译运行,程序会在每次调用 fact 时输出栈信息。可以看到在 fact(0) 中调用 print_call_stack_info() 有 8 行输出(也就是有 8 个栈帧),在 fact(5) 中则是 3 行输出(3 个栈帧)。这表示从 fact(5) 递归调用到 fact(0),创建了 5 个栈帧。每个栈帧的大小是 0x20


                
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值