2021 XV6 4:traps

news2025/1/11 18:38:23

目录

1.RISC-V assenbly

2.Backtrace

 3.Alarm


1.RISC-V assenbly

第一个任务是阅读理解,一共有6个问题。

1.Which registers contain arguments to functions? For example, which register holds 13 in main's call to printf?

具体来说就是a0,a1几个寄存器存了相应的系统调用参数,a7存的是系统调用号。

2.Where is the call to function f in the assembly code for main? Where is the call to g? (Hint: the compiler may inline functions.)

 这个好像汇编代码直接内联了。

3.At what address is the function printf located?

 这里很明显了,跳到的地址是1552+ra=1552+0x30=0x640

4.What value is in the register ra just after the jalr to printf in main?

 

 这个auipc噢,用那个跳转的16进制地址减去1552就可以算出来,实际上就是存的0x097当前的地址,这个auipc就是把当前pc和后面那个立即数的低12位取0相加得到的。

jalr会在跳转之后把ra加8,也就是ra+8=0x38,即下一条返回执行的地址。

5.Run the following code.

	unsigned int i = 0x00646c72;
	printf("H%x Wo%s", 57616, &i);
      

What is the output? Here's an ASCII table that maps bytes to characters.

The output depends on that fact that the RISC-V is little-endian. If the RISC-V were instead big-endian what would you set i to in order to yield the same output? Would you need to change 57616 to a different value?

这考察大端小端的问题,第一个就是10进制转8进制,第二个是小端的输出,输出726c64

6.In the following code, what is going to be printed after 'y='? (note: the answer is not a specific value.) Why does this happen?

	printf("x=%d y=%d", 3);

这里输出的就是寄存器a1里边的值,是什么值就是啥。

2.Backtrace

实现一个系统调用,用来打印调用的栈的系统信息的。据说对debug有用,虽然我还没想到哪里可以用。

首先我们得熟悉一下系统里边调用的层次结构:

 我们来看一下这张图,从上往下看,高地址在高位,但是栈是向低地址增长的。首先呢是存个return address,也就是返回执行的地址,然后存的就是prev frame辣,这就是我们要打印的东西,xv6还提示我们可以用一条内联汇编去取出当前的栈帧指针,这个指针是指向那个return address的上一个位置的,意味着我们可以用-8,-16取到返回地址以及上一个栈帧的指针,那么我们写个循环就好了对吧。

那么循环条件是什么?我们在给一个程序分配栈时,按照页为单位,其中每个页面之间有个保护页面。

Xv6 allocates one page for each stack in the xv6 kernel at PAGE-aligned address.

意思就是我们的栈桢指针应该是指向一个页的顶部的,所以当他不等于的时候就是循环结束的条件。

void
backtrace(void)
{
  printf("backtrace:\n");
  // fp保存当前栈帧指针
  uint64 fp=r_fp();
  while(fp!=PGROUNDUP(fp))
  {
    uint64 ret_addr=*(uint64 *)(fp-8);
    printf("%p\n", ret_addr);
    fp=*(uint64 *)(fp-16);
  }
}

最后在sys_sleep里边backtrace一下就行了,当然,系统调用号以及入口一些细节按照xv6里边来就行了。

执行bttest如下所示:

 3.Alarm

这里的任务就是加个系统调用来处理信号。这个信号处理流程大概是这样的:

sigalarm(time,handler),设置每隔time的ticks执行handler,这个handler是用户态的函数,在函数末尾我们要用sigreturn返回。

其实这里有个东西我想了挺久的,如果说在进入trap之前已经存下来了所有寄存器的话,为什么还要用sigreturn处理用户的返回呢?这个其实是因为,首先啊,在time到的时候,我们为了要返回用户态执行handler,我们要设置返回的trapframe是handler的地址,然后呢,如果没有sigreturn会怎么样?trap返回然后恢复寄存器,handler继续执行,然后返回到原来中断的函数里边执行,那么,原来的context其实可能已经打乱了,所以,我们得用一个sigreturn来恢复sigalarm之前的上下文。

具体思路及步骤如下所示:

1.首先还是处理系统调用号以及一些入口

2.在sysproc.c里边写这两个函数:

uint64
sys_sigalarm(void)
{
  int ticks=0;
  uint64 handler=0;
  struct proc *p=myproc();
  if (argint(0, &ticks)<0)
  {
    return -1;
  }

  if (argaddr(1, &handler)<0)
  {
    return -1;
  }

  p->ticks=ticks;
  p->has_return=1;
  p->pass_ticks=0;
  p->handler=(void (*)())handler;
  // printf("In sys_sigalarm pass_ticks:%d   ticks:%d    epc:%p\n",p->pass_ticks,p->ticks,p->trapframe->epc);
  return 0;
}

uint64
sys_sigreturn(void)
{
  struct proc *p=myproc();
  memmove(p->trapframe,p->signal_trapframe,sizeof(struct trapframe));
  p->pass_ticks=0;
  p->has_return=1;
  // printf("In sys_sigreturn pass_ticks:%d   ticks:%d   epc:%p\n",p->pass_ticks,p->ticks,p->trapframe->epc);
  return 0;
}

sigalarm接收时间戳和handler两个参数,并且添加到进程的数据结构里面。

sigreturn重新设置时间戳,并且标记目前正在执行handler,试着想一下,如果一个handler要执行很久,那么我们在handler里面又会handler,这是我们不期望的,也就是说,当执行handler时,就一直执行完而屏蔽sigalarm设置的handler。

3.在trap.c里边修改如下:

  // give up the CPU if this is a timer interrupt.
  if(which_dev == 2){
    // printf("In trap pass_ticks:%d   ticks:%d    epc:%p\n",p->pass_ticks,p->ticks,p->trapframe->epc);
    if (p->ticks==0)
    {
      yield();
      usertrapret();
    }
    else
    {
      int pass_ticks=p->pass_ticks+1;
      if (pass_ticks>=p->ticks&&p->has_return==1)
      {
        // 记录时钟中断前上下文
        p->signal_trapframe=(struct trapframe*)kalloc();
        memmove(p->signal_trapframe,p->trapframe,sizeof(struct trapframe));
        // 调整返回执行地址
        p->trapframe->epc=(uint64)p->handler;
        p->has_return=0;
      }
      else
      {
        p->pass_ticks=pass_ticks;
      }
    }
    yield();
  }

 这里的逻辑就是应该已经很清晰了~

执行alarmtest如下所示:

这个实验通过backtrace以及一些信号系统调用让我们理解了系统调用的流程以及一些汇编指令的作用,当然,收获最大的是这个信号处理流程。

 

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/21333.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Docker入门

目录 Docker的作用 Docker的核心概念 Docker安装 镜像命令 镜像下载 查看镜像 搜索镜像 删除镜像 容器命令 创建容器 列出容器 新建并启动容器(最常使用) 守护态运行 启动容器 终止容器 重启容器 进入容器 attach命令 exec命令&#xff08;最常使用&#xff09; 退出容器…

【JavaEE】一文掌握 Ajax

&#x1f431;‍&#x1f3cd;目录1. AJAX 简介2. 伪造Ajax演示3. jQuery.ajax3.1 简单测试&#xff0c;使用最原始的HttpServletResponse处理3.2 使用ajax动态构建前端表格3.3 登录提示效果小demo4. 练习小demo&#xff0c;实现百度搜索框的动态内容提示5. 总结&#xff1a;1.…

纸牌游戏洗牌发牌排序算法设计

纸牌游戏洗牌发牌排序算法设计 本文提供纸牌游戏设计制作的基础部分&#xff0c;即洗牌&#xff0c;发牌&#xff0c;牌张排序排列显示的算法。 以及游戏开始时间使用时间的显示。我是用简单的C语言编译器MySpringC在安卓手机上编写的。此是游戏的框架&#xff0c;供游戏设计者…

计算机网络4小时速成:网络层,虚电路和数据包服务,ipv4,ABC类地址,地址解析协议ARP,子网掩码,路由选择协议,路由器

计算机网络4小时速成&#xff1a;网络层&#xff0c;虚电路和数据包服务&#xff0c;ipv4,ABC类地址&#xff0c;地址解析协议ARP&#xff0c;子网掩码&#xff0c;路由选择协议&#xff0c;路由器 2022找工作是学历、能力和运气的超强结合体&#xff0c;遇到寒冬&#xff0c;…

关于瑞萨R7 的CANFD切换为经典CAN

首先,R7的CANFD是兼容CAN通讯的&#xff0c;在R7芯片他们公用相同的寄存器&#xff0c;至于发出来的帧是CANFD还是CAN取决于协议的不同。 CANFD是可变速率数据段为可变长度&#xff0c;扩展到64Byte&#xff0c;仲裁段和数据段的速率不相同。CANFD新增了FDF,BRS,ESI。FDF表示是…

牛客_小白月赛_61

传送门 A 如果不是特意防止溢出了&#xff0c;那么需要用long,否则会一直卡 很普通的写法,超了就 1, 最后补上一个 1就行 (所以, 这题我wa了8次, 卡了半个小时,就是因为没开 long ! ! !) package com.csh.A; /*** author :Changersh* date : 2022/11/18*/import java.io.*; i…

day02 springmvc

day02 springmvc 第一章 RESTFul风格交互方式 第一节 RESTFul概述 1. REST的概念 REST&#xff1a;Representational State Transfer&#xff0c;表现层资源状态转移。 定位&#xff1a;互联网软件架构风格倡导者&#xff1a;Roy Thomas Fielding文献&#xff1a;Roy Thom…

Android源码学习---init

init&#xff0c;是linux系统中用户空间的第一个进程&#xff0c;也是Android系统中用户空间的第一个进程。 位于/system/core/init目录下。 分析init int main(int argc, char **argv) { //设置子进程退出的信号处理函数 sigchld_handler act.sa_handler sigchld_handler;…

【博学谷学习记录】超强总结,用心分享丨人工智能 Python面向对象 学习总结之Python与Java的区别

目录前言简述面向对象类对象特性前言 经过学习&#xff0c;对Python面向对象部分有了一定的了解。 总结记录&#xff1a;面向对象上Python与Java的部分区别 简述 从类、对象、特性三个层面来简述其部分区别 面向对象 类 PythonJava定义class ClassName(object):passpubl…

2000-2020年各省固定资本存量数据

2000-2020年各省资本存量数据 1&#xff1a;来源&#xff1a;统计NJ、各省统计NJ 2、时间&#xff1a;2000-2020年 3、包括&#xff1a;30个省 4、数据说明&#xff1a;含原始数据和计算过程及最终结果 4、指标说明&#xff1a; 参考文献&#xff1a; 单豪杰&#xff08;…

【微服务架构组件之注册中心】注册中心选型-我只选nacos

注册中心的产生是基于用来解耦服务提供者(Provider)与消费者&#xff08;Consumer&#xff09;的关系&#xff0c;分布式设计架构下&#xff0c;众多的服务提供者的数量并不是动态不变的&#xff0c;在传统的静态LB的方案中&#xff0c;无法很好感知这种变化&#xff1b; 在分…

[附源码]java毕业设计网上宠物商店

项目运行 环境配置&#xff1a; Jdk1.8 Tomcat7.0 Mysql HBuilderX&#xff08;Webstorm也行&#xff09; Eclispe&#xff08;IntelliJ IDEA,Eclispe,MyEclispe,Sts都支持&#xff09;。 项目技术&#xff1a; SSM mybatis Maven Vue 等等组成&#xff0c;B/S模式 M…

进度条——不仅仅是语言层面上的小程序

文章目录\r和\n进度条完整代码\r和\n 在老式键盘上&#xff0c;回车键是这样的形状 但是该键的功能它不仅仅是回车&#xff0c;而是回车换行&#xff01; 这里需要明白两个概念&#xff1a; 回车&#xff1a;光标移动到当前行的行首 换行&#xff1a;光标移动到当前位置的…

跟艾文学编程《Python基础》Anaconda 安装

作者&#xff1a;艾文&#xff0c;计算机硕士学位&#xff0c;企业内训讲师和金牌面试官&#xff0c;公司资深算法专家&#xff0c;现就职BAT一线大厂。 邮箱&#xff1a;1121025745qq.com 博客&#xff1a;https://edu.csdn.net/lecturer/894?spm1003.2001.3001.4144 内容&am…

原生AJAX

&#x1f468;‍&#x1f4bb;个人主页&#xff1a;微微的猪食小窝 欢迎 点赞&#x1f44d; 收藏⭐ 留言&#x1f4dd; 加关注✅! 本文由 微微的猪食小窝 原创 1、AJAX 简介 AJAX 全称为Asynchronous Javascript And XML,就是异步的JS 和 XML. 通过AJAX可以在浏览器中向服务器…

Vue3留言墙项目——主体部分静态、mock

文章目录主体头部主体关键部分小卡片组件创建mock数据以及使用主体头部 主体部分显示的内容&#xff0c;根据头部点击的是留言墙还是照片墙的按钮&#xff0c;显示不同的内容。 将照片墙和留言墙要渲染的数据抽取到一个js中&#xff0c;在导入的Main.vue&#xff08;主体页面&…

[go]汇编ASM简介

文章目录汇编(ASM)寄存器帧指针FP常见指令函数示例生成汇编Go汇编代码主要用于优化和与底层系统交互&#xff0c;并不会像其它的经典汇编代码那样独立运行。汇编(ASM) Go ASM是一种被Go编译器使用的特殊形式的汇编语言&#xff08;伪汇编&#xff09;&#xff0c;它基于Plan9输…

记录一次Powerjob踩的坑(Failed to deserialize message)

一. 问题描述: 在本地开发环境, server端和worker都运行正常. 但是发布到SIT环境(容器)的时候, 服务端却监测不到worker(worker可以找到服务端) 二. 问题表现: 1.服务端看不到Worker信息 2. 服务端日志信息 : Failed to deserialize message from [akka://oms111.111.111…

ECMAScript modules规范示例详解

引言 很多编程语言都有模块这一概念&#xff0c;JavaScript 也不例外&#xff0c;但在 ECMAScript 2015 规范发布之前&#xff0c;JavaScript 没有语言层面的模块语法。模块实际上是一种代码重用机制&#xff0c;要实现代码重用&#xff0c;将不同的功能划分到不同的文件中是必…

pycharm安装并加载编译器,设置背景图片,手把手详细操作

pycharm安装并加载编译器&#xff0c;设置背景图片&#xff0c;手把手详细操作 pycharm社区版&#xff08;免费&#xff09;下载官网 双击安装包&#xff0c;选择安装路径 勾选这两个&#xff0c;其实全不勾也没事 下一步默认就行&#xff0c;点install 安装完成后&#xf…