2023-2024-1 20232817《Linux内核原理与分析》第七周作业

分析 system_call 中断处理过程

MenuOS迁移到RISC-V架构

MenuOS 是接下来四次实验的平台。但是由于MenuOS原本设计是为x86架构所服务的,如果需要在RISC-V架构上的机器上运行,就必须对关键部分的汇编代码进行修改。

首先使用以下命令克隆MenuOS

cd ~/riscv64_oslab/
mkdir MenuOS
cd MenuOS
git clone https://github.com/mengning/menu.git

克隆后,进入menu目录,使用你喜欢的编辑器对其中的TimeAsm函数进行修改,修改内容如下:

int TimeAsm(int argc, char *argv[])
{
    time_t tt;
    struct tm *t;
    asm volatile(
        "li a0,201\n\t"
        "ecall \n\t"
        "sd a0, %0\n\t"
        : "=m" (tt)
     );
    t = localtime(&tt);
    printf("time:%d:%d:%d:%d:%d:%d\n",t->tm_year+1900, t->tm_mon, t->tm_mday, t->tm_hour, t->tm_min, t->tm_sec);
    return 0;
}

另外一个需要修改的文件是Makefile,这个文件的修改非常重要,将决定产生的什么架构的执行文件。

同样,请使用你喜欢的编辑器,打开Makefile,将其修改为以下内容:

#
# Makefile for Menu Program
#

CC_PTHREAD_FLAGS			 = -lpthread
CC_FLAGS                     = -c 
CC_OUTPUT_FLAGS				 = -o
CC                           = riscv64-linux-gcc
RM                           = rm
RM_FLAGS                     = -f

TARGET  =   test
OBJS    =   linktable.o  menu.o test.o

all:	$(OBJS)
	$(CC) $(CC_OUTPUT_FLAGS) $(TARGET) $(OBJS) 
rootfs:
	riscv64-linux-gcc -o init linktable.c menu.c test.c  -static -lpthread
	riscv64-linux-gcc -o hello hello.c -static
	find init hello | cpio -o -Hnewc |gzip -9 > ../rootfs.img
	qemu-system-riscv64 -M virt \
			    -kernel ../linux-5.19.16/arch/riscv/boot/Image \
		        -initrd ../rootfs.img \
                -nographic
.c.o:
	$(CC) $(CC_FLAGS) $<

clean:
	$(RM) $(RM_FLAGS)  $(OBJS) $(TARGET) *.bak

需要注意的是,本次实验需要使用 qemu-system-riscv64qemu-system-riscv64 , 请完成第三次实验后,再来做此次实验。

使用以下命令进行编译和运行:

make -j$(nproc)
make rootfs -j$(nproc)

成功运行后,将会显示以下信息:

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

CWrite和的编写

现在我们在menu目录下, 使用你喜欢的编辑器修改test.c。这里使用神之编辑器emacs进行修改。

emacs test.c

打开之后,添加以下内容:

CWrite函数内容如下:

int CWrite(void){
  char s[]="hello, world\n";
	write(1,s,13);
	return 0;
  return 0;
}

WriteAsm函数如下:

int WriteAsm(void){
  char s[] = "hello, world\n";

    __asm__ volatile(
		    "li a2, 13\n"
		    "li a0, 1\n"
		    "mv a1, %[str]\n"
	    	    "li a7, 64\n"
		    "ecall \n"
		    :
		    : [str] "r" (s)
    );
  return 0;
}

同样使用以下命令进行编译和运行:

make -j$(nproc)
make rootfs -j$(nproc)

启动MenuOS后:

输入 help 后回车,显示如下信息:

image-20231105212850985

再次输入 write 后回车,MenuOS输出以下信息:

image-20231105212959159

输入 write-asm 后回车,MenuOS输出以下信息:

image-20231105213246034

GDB调试sys_write函数

使用你喜欢的编辑器在menu目录下,编写start-gdb.sh ,这里依旧使用emacs。

start-gdb.sh 的内容如下:

#!/bin/sh

qemu-system-riscv64 -M virt \
			    -kernel ../linux-5.19.16/arch/riscv/boot/Image \
		        -initrd ../rootfs.img \
                -nographic \
                -s -S

使用以下命令赋予start-gdb.sh 执行的权限:

chmod +x start-gdb.sh

使用以下命令启动 start-gdb.sh

./start-gdb.sh

启动后,shell中应当不显示任何内容,如下所示:

image-20231105221503598

另开一个终端,进入MenuOS的目录下,使用以下命令启动 gdb-multiarch

gdb-multiarch linux-5.19.16/vmlinux

启动之后,输入 target remote:1234 建立连接,显示如下信息说明连接建立完成:

image-20231105221724247

依次使用以下命令进行 sys_write 的调试:

b sys_write
c
layout split

最终界面将显示如下信息:

image-20231105221933745

此时,将启动 gdb-multiarch 的终端和启动 ./start-gdb.sh 的终端分别分屏左右,方便查看调试过程中的程序的输出,如下图所示:

image-20231106161606896

执行上面打断点的操作后,在右侧图中的的最后一行显示:[ 0.507884] Run /init as init process 说明Linux 内核已经初始化完成。
现在使用 十一次 c 命令,使得MenuOS加载到shell,如下图所示:

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

现在在MenuOS中输入 write-asm 回车之后, MenuOS将会暂停输出。然后在左侧gdb窗口中输入命令 c ,MenuOS将会显示以下信息:

image-20231106162854338

此时可以开始分析 Cwrite 中使用系统调用 write 的过程。首先使用以下命令对 handle_exception 打断点:

b handle_exception

然后使用命令 c 进入到 handle_exception 断点处。在 handle_exception 函数中,根据异常号判断是否是系统调用。如果是系统调用,控制权会传递到系统调用处理的分发函数。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

generic_handle_arch_irq 是 Linux 内核中的一个通用中断处理函数,它用于处理系统中断的基本工作。这个函数的主要作用是将控制权传递给适当的中断处理函数。在 Linux 内核中,每个中断都有一个对应的中断处理函数,用于处理特定类型的中断。generic_handle_arch_irq 通过查询中断描述符表(Interrupt Descriptor Table,IDT)来确定要执行的中断处理函数,并将控制权转交给它。

使用命令 c 进入 ksys_write 断点处。在 SYSCALL_DEFINE3 的函数中的返回语句 return ksys_write(fd, buf, count); ,如下图所示:

image-20231106162942747

继续使用 si 命令,将程序将执行下一条汇编语句,如下图所示:

image-20231106163210213

system_call 调用过程如下:

ecall指令触发中断
handle_exception处理中断
handle_syscall处理系统调用
系统调用sys_write
ret_from_exception中断返回:
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值