MIT XV6 - 1.1 Lab: Xv6 and Unix utilities - user/_sleep 是什么?做什么?

接上文 MIT XV6 - 1.1 Lab: Xv6 and Unix utilities - sleep 是怎样练成的?

user/_sleep 是什么?

book-riscv-rev3.pdf 3.8节有对Xv6 binary文件的格式描述

Xv6 binaries are formatted in the widely-used ELF format, defined in (kernel/elf.h). An ELF binary
consists of an ELF header, struct elfhdr (kernel/elf.h:6), followed by a sequence of program
section headers, struct proghdr (kernel/elf.h:25). Each progvhdr describes a section of the
application that must be loaded into memory; xv6 programs have two program section headers:
one for instructions and one for data.

  • 让我们验证一下他的文件格式
    riscv64-unknown-elf-readelf -h user/_sleep  
    ELF Header:                                 Magic:   7f 45 4c 46 02 01 01 00 00 00 00 00 00 00 00 00          # ELF 文件的魔数,用于标识文件类型Class:                             ELF64                          # 64 位 ELF 文件Data:                              2's complement, little endian  # 使用 2 的补码表示数字,小端序存储Version:                           1 (current)                    # ELF 格式的当前版本OS/ABI:                            UNIX - System V                # 目标操作系统为 UNIX System VABI Version:                       0                              # ABI 版本号Type:                              EXEC (Executable file)         # 这是一个可执行文件Machine:                           RISC-V                         # 目标架构为 RISC-VVersion:                           0x1                            # ELF 文件版本Entry point address:               0x64                           # 程序入口点的虚拟地址Start of program headers:          64 (bytes into file)           # 程序头表在文件中的偏移量Start of section headers:          31008 (bytes into file)        # 节头表在文件中的偏移量Flags:                             0x5, RVC, double-float ABI     # 标志位:RISC-V 压缩指令集,双精度浮点数 ABISize of this header:               64 (bytes)                     # ELF 头的大小Size of program headers:           56 (bytes)                     # 每个程序头的大小Number of program headers:         4                              # 程序头的数量Size of section headers:           64 (bytes)                     # 每个节头的大小Number of section headers:         18                             # 节头的数量Section header string table index: 17                             # 节头字符串表的索引
    

我们知道,在Unix系统中,一个新进程的诞生是通过forkexec配合得来的,通过fork创建一个副本,然后通过exec将指定的binary加载进内存空间中并开始执行,教材中也对此有所讲解,依然是book-riscv-rev3.pdf 3.8节,简单看一眼

在这里插入图片描述

  • 让我们看看我们的 user/_sleep

    riscv64-unknown-elf-objdump -p user/_sleep user/_sleep:     file format elf64-littleriscvProgram Header:
    0x70000003 off    0x0000000000006af8 vaddr 0x0000000000000000 paddr 0x0000000000000000 align 2**0filesz 0x000000000000005a memsz 0x0000000000000000 flags r--
    LOAD off    0x0000000000001000 vaddr 0x0000000000000000 paddr 0x0000000000000000 align 2**12filesz 0x0000000000001000 memsz 0x0000000000001000 flags r-x
    LOAD off    0x0000000000002000 vaddr 0x0000000000001000 paddr 0x0000000000001000 align 2**12filesz 0x0000000000000000 memsz 0x0000000000000020 flags rw-
    STACK off    0x0000000000000000 vaddr 0x0000000000000000 paddr 0x0000000000000000 align 2**4filesz 0x0000000000000000 memsz 0x0000000000000000 flags rw-
    
  • 让我们来看看AI是怎么解释的
    在这里插入图片描述

  • 当然我们的 user/_sleep 里面还有更多东西

    riscv64-unknown-elf-objdump -h user/_sleep  
    Sections:                                                                        
    Idx Name          Size      VMA               LMA               File off  Algn   # 列标题:索引、名称、大小、虚拟地址、加载地址、文件偏移、对齐0 .text         0000082a  0000000000000000  0000000000000000  00001000  2**1   # 代码段:包含可执行指令CONTENTS, ALLOC, LOAD, READONLY, CODE                           # 属性:有内容、已分配、可加载、只读、代码1 .rodata       000007d0  0000000000000830  0000000000000830  00001830  2**3   # 只读数据段:包含常量数据(如字符串常量)CONTENTS, ALLOC, LOAD, READONLY, DATA                           # 属性:有内容、已分配、可加载、只读、数据2 .data         00000000  0000000000001000  0000000000001000  00002000  2**0   # 数据段:包含已初始化的全局变量CONTENTS, ALLOC, LOAD, DATA                                      # 属性:有内容、已分配、可加载、数据3 .bss          00000020  0000000000001000  0000000000001000  00002000  2**3   # BSS段:包含未初始化的全局变量ALLOC                                                           # 属性:已分配4 .debug_info   00000ff8  0000000000000000  0000000000000000  00002000  2**0   # 调试信息段:包含DWARF调试信息CONTENTS, READONLY, DEBUGGING, OCTETS                           # 属性:有内容、只读、调试用、字节数据5 .debug_abbrev 00000643  0000000000000000  0000000000000000  00002ff8  2**0   # 调试缩写表:DWARF调试信息的缩写表CONTENTS, READONLY, DEBUGGING, OCTETS                           # 属性:有内容、只读、调试用、字节数据6 .debug_loc    00001f21  0000000000000000  0000000000000000  0000363b  2**0   # 调试位置信息:变量位置信息CONTENTS, READONLY, DEBUGGING, OCTETS                           # 属性:有内容、只读、调试用、字节数据7 .debug_aranges 000000f0  0000000000000000  0000000000000000  00005560  2**4  # 调试地址范围:用于快速定位调试信息CONTENTS, READONLY, DEBUGGING, OCTETS                           # 属性:有内容、只读、调试用、字节数据8 .debug_line   000011ab  0000000000000000  0000000000000000  00005650  2**0   # 调试行号信息:源代码行号映射CONTENTS, READONLY, DEBUGGING, OCTETS                           # 属性:有内容、只读、调试用、字节数据9 .debug_str    000002e4  0000000000000000  0000000000000000  000067fb  2**0   # 调试字符串表:调试信息中的字符串CONTENTS, READONLY, DEBUGGING, OCTETS                           # 属性:有内容、只读、调试用、字节数据
    10 .comment      00000019  0000000000000000  0000000000000000  00006adf  2**0   # 注释段:包含编译器版本等信息CONTENTS, READONLY                                              # 属性:有内容、只读
    11 .riscv.attributes 0000005a  0000000000000000  0000000000000000  00006af8  2**0 # RISC-V特定属性段CONTENTS, READONLY                                              # 属性:有内容、只读
    12 .debug_frame  000004e0  0000000000000000  0000000000000000  00006b58  2**3   # 调试帧信息:用于栈回溯CONTENTS, READONLY, DEBUGGING, OCTETS                           # 属性:有内容、只读、调试用、字节数据
    13 .debug_ranges 00000050  0000000000000000  0000000000000000  00007038  2**0   # 调试范围信息:用于描述变量范围CONTENTS, READONLY, DEBUGGING, OCTETS                           # 属性:有内容、只读、调试用、字节数据
    

    我就不解释了,这个东西给我一天也解释不清楚,解释不完全(是真的不清楚)

user/_sleep 做什么?

让我们打开 user/sleep.asm 看一下汇编代码

   0:	1141                	addi	sp,sp,-162:	e406                	sd	ra,8(sp)4:	e022                	sd	s0,0(sp)6:	0800                	addi	s0,sp,16if (argc != 2)8:	4789                	li	a5,2a:	02f50063          	beq	a0,a5,2a <main+0x2a>{fprintf(2, "Usage: sleep <seconds>\n");e:	00001597          	auipc	a1,0x112:	82258593          	addi	a1,a1,-2014 # 830 <malloc+0x100>16:	853e                	mv	a0,a518:	00000097          	auipc	ra,0x01c:	62e080e7          	jalr	1582(ra) # 646 <fprintf>exit(1);20:	4505                	li	a0,122:	00000097          	auipc	ra,0x026:	2fc080e7          	jalr	764(ra) # 31e <exit>}if (sleep(atoi(argv[1])) != 0)2a:	6588                	ld	a0,8(a1)2c:	00000097          	auipc	ra,0x030:	1ec080e7          	jalr	492(ra) # 218 <atoi>34:	00000097          	auipc	ra,0x038:	37a080e7          	jalr	890(ra) # 3ae <sleep>3c:	cd19                	beqz	a0,5a <main+0x5a>{fprintf(2, "sleep: failed to sleep\n");3e:	00001597          	auipc	a1,0x142:	80a58593          	addi	a1,a1,-2038 # 848 <malloc+0x118>46:	4509                	li	a0,248:	00000097          	auipc	ra,0x04c:	5fe080e7          	jalr	1534(ra) # 646 <fprintf>exit(1);50:	4505                	li	a0,152:	00000097          	auipc	ra,0x056:	2cc080e7          	jalr	716(ra) # 31e <exit>}exit(0);5a:	4501                	li	a0,05c:	00000097          	auipc	ra,0x060:	2c2080e7          	jalr	706(ra) # 31e <exit>

注意这一条指令

  38:	37a080e7          	jalr	890(ra) # 3ae <sleep>

这是一条跳转指令,地址是 3ae,经过搜索可以看到 sleep 函数的汇编代码

00000000000003ae <sleep>:                      # 函数入口点,地址为 0x3ae
.global sleep                                  # 声明 sleep 为全局符号
sleep:                                         # 函数标签li a7, SYS_sleep                              # 将系统调用号 13 (SYS_sleep) 加载到寄存器 a73ae:	48b5                li	a7,13          # 机器码:48b5 表示 li a7,13ecall                                         # 执行系统调用指令3b0:	00000073          	ecall              # 机器码:00000073 表示 ecallret                                           # 从函数返回3b4:	8082                ret                # 机器码:8082 表示 ret

我们忽略其他各种分支判断以及错误码打印,exit调用等等, 可以看到sleep.c的核心就是在条件达成时,调用函数sleep,而 sleep函数内的实现就是利用 ecall 指令触发系统调用,当系统调用完成后,函数返回。

瞎谈

有大佬说过 Algorithms + Data Structures = Programs

那么从操作系统的角度来看,是不是 Data + SysCall = Programs 也是成立的?因为程序的一切的一切最终都是要把你想做的事情组织成一条条数据,通过系统调用的方式来达成目的?比如播放音乐、播放视频、玩video game,毕竟系统调用应该是应用程序控制硬件资源的唯一途径(吧?)。

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

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

相关文章

【AI科技】AMD ROCm 6.4 新功能:突破性推理、即插即用容器和模块化部署,可在 AMD Instinct GPU 上实现可扩展 AI

AMD ROCm 6.4 新功能&#xff1a;突破性推理、即插即用容器和模块化部署&#xff0c;可在 AMD Instinct GPU 上实现可扩展 AI 现代 AI 工作负载的规模和复杂性不断增长&#xff0c;而人们对性能和部署便捷性的期望也日益提升。对于在 AMD Instinct™ GPU 上构建 AI 和 HPC 未来…

【含文档+PPT+源码】基于微信小程序连锁药店商城

项目介绍 本课程演示的是一款基于微信小程序连锁药店商城&#xff0c;主要针对计算机相关专业的正在做毕设的学生与需要项目实战练习的 Java 学习者。 1.包含&#xff1a;项目源码、项目文档、数据库脚本、软件工具等所有资料 2.带你从零开始部署运行本套系统 3.该项目附带的…

node.js模块化步骤(各标准区别)CommonJS规范、AMD规范、UMD规范、ES Modules (ESM)

前后端建议统一使用ESM 文章目录 Node.js模块化发展历程与标准对比一、模块化的意义1.1 解决的核心问题1.2 没有模块化的问题 二、CommonJS规范2.1 核心特征2.2 实现示例 三、AMD (Asynchronous Module Definition)3.1 特点3.2 代码示例 四、UMD (Universal Module Definition)…

人工智能与智能合约:如何用AI优化区块链技术中的合约执行?

引言&#xff1a;科技融合的新风口 区块链和人工智能&#xff0c;是当前最受瞩目的两大前沿技术。一个以去中心化、可溯源的机制重构信任体系&#xff0c;另一个以智能学习与决策能力重塑数据的价值。当这两项技术相遇&#xff0c;会碰撞出什么样的火花&#xff1f; 智能合约作…

RabbitMQ-api开发

前言 MQ就是接收并转发消息 核心概念 admin是用户 每个虚拟机上都有多个交换机 快速入门 引入依赖 <dependency><groupId>com.rabbitmq</groupId><artifactId>amqp-client</artifactId><version>5.22.0</version></dependen…

PostgreSQL Patroni集群组件作用介绍:Patroni、etcd、HAProxy、Keepalived、Watchdog

1. Watchdog 简介 1.1 核心作用 • 主节点故障检测 Watchdog 会定时检测数据库主节点&#xff08;或 Pgpool 主节点&#xff09;的运行状态。 一旦主节点宕机&#xff0c;它会发起故障切换请求。 • 协调主备切换 多个 Pgpool 节点时&#xff0c;Watchdog 保证只有一个 Pg…

【多种不同提交方式】通过springboot实现与前端网页数据交互(非常简洁快速)

【多种不同提交方式】通过springboot实现与前端网页数据交互 提示&#xff1a;帮帮志会陆续更新非常多的IT技术知识&#xff0c;希望分享的内容对您有用。本章分享的是springboot的使用。前后每一小节的内容是存在的有&#xff1a;学习and理解的关联性。【帮帮志系列文章】&am…

使用 AI 如何高效解析视频内容?生成思维导图或分时段概括总结

一、前言 AI 发展的如此迅速&#xff0c;有人想通过 AI 提效对视频的解析&#xff0c;怎么做呢&#xff1f; 豆包里面有 AI 视频总结的功能&#xff0c;可以解析bilibili网站上部分视频&#xff0c;如下图所示&#xff1a; 但有的视频解析时提示&#xff1a; 所以呢&#x…

鞅与停时 - 一种特别的概率论问题

讨论一个有趣的概率问题&#xff1a; [P3334 ZJOI2013] 抛硬币 - 洛谷 实际上是一个猴子打字问题&#xff0c;考虑一直无规律随即打字的猴子&#xff0c;键盘上只有A-Z一共26个字母&#xff0c;对于一个特定的字符串 S S S &#xff1a; ABCABCAB &#xff0c;能否在有限的打…

arcgis和ENVI中如何将数据输出为tif

一、arcgis中转换为tif 右键图层&#xff1a; Data -> Export Data, 按照图示进行选择&#xff0c;选择tiff格式导出即可&#xff0c;还可以选择其他类型的格式&#xff0c;比如envi。 二、 ENVI中转换为tif File -> Save As -> Save As (ENVI, NITF, TIFF, DTED) …

如何用命令行判断一个exe是不是c#wpf开发的

在powershell下执行 $assembly [Reflection.Assembly]::ReflectionOnlyLoadFrom("你的exe全路径") $references $assembly.GetReferencedAssemblies() echo $assembly $references | Where-Object { $_.Name -match "PresentationFramework|PresentationCore…

2025.05.07-华为机考第三题300分

📌 点击直达笔试专栏 👉《大厂笔试突围》 💻 春秋招笔试突围在线OJ 👉 笔试突围OJ 03. 城市紧急救援队伍协同规划 问题描述 智慧城市建设中,卢小姐负责设计一套紧急救援队伍协同系统。城市被规划为一个 n n n \times n

深入理解Redis SDS:高性能字符串的终极设计指南

&#x1f4cd; 文章提示 10分钟掌握Redis核心字符串设计 | 从底层结构到源码实现&#xff0c;揭秘SDS如何解决C字符串七大缺陷&#xff0c;通过20手绘图示与可运行的C代码案例&#xff0c;助你彻底理解二进制安全、自动扩容等核心机制&#xff0c;文末附实战优化技巧&#xff…

jupyter notebook汉化教程

本章教程记录&#xff0c;jupyter notebook汉化步骤&#xff0c;如果对汉化有需求的小伙伴可以看看。 一、安装jupyter 如果你是安装的anaconda的那么默认是包含了Jupyter notebook的&#xff0c;如果是miniconda或者基础python&#xff0c;默认是不包含的jupyter组件的&#x…

模拟设计中如何减小失配

Xx 芯片测试结果显示&#xff0c;offset 指标偏高&#xff0c;不符合指标要求。所以查看了资料&#xff0c;温习了减小的失配的方法。 注意点一&#xff1a; 将所有offet折算到输入端&#xff0c;得到以下公式&#xff1a; 可以看到a&#xff09;阈值电压失配直接折算成输…

C++ 与 Lua 联合编程

在软件开发的广阔天地里&#xff0c;不同编程语言各有所长。C 以其卓越的性能、强大的功能和对硬件的直接操控能力&#xff0c;在系统开发、游戏引擎、服务器等底层领域占据重要地位&#xff0c;但c编写的程序需要编译&#xff0c;这往往是一个耗时操作&#xff0c;特别对于大型…

烤箱面包烘焙状态图详解:从UML设计到PlantUML实现

题目&#xff1a;假设你正着手设计一个烤箱。建立一个跟踪烤箱中面包状态的状态图。要包括必要的触发器事件、动作和监视条件。 一、状态图概述 状态图是UML&#xff08;统一建模语言&#xff09;中的一种行为图&#xff0c;它用于描述系统中对象的状态变化以及触发这些变化的…

三款实用工具推荐:配音软件+Windows暂停更新+音视频下载!

各位打工人请注意&#xff01;今天李师傅掏出的三件套&#xff0c;都是经过实战检验的效率放大器。先收藏再划走&#xff0c;说不定哪天就能救命&#xff01; 一.祈风TTS-配音大师 做短视频的朋友肯定深有体会——配个音比写脚本还费劲&#xff01;要么付费买声音&#xff0c…

物流无人机结构与载货设计分析!

一、物流无人机的结构与载货设计模块运行方式 1.结构设计特点 垂直起降与固定翼结合&#xff1a;针对复杂地形&#xff08;如山区、城市&#xff09;需求&#xff0c;采用垂直起降&#xff08;VTOL&#xff09;与固定翼结合的复合布局&#xff0c;例如“天马”H型无人机&am…

Decode rpc invocation failed: null -> DecodeableRpcInvocation

DecodeableRpcInvocation 异常情况解决方法 错误警告官方FAQ 异常情况 记录一下Dubbo调用异常 java.util.concurrent.ExecutionException: org.apache.dubbo.remoting.TimeoutException: Waiting server-side response timeout by scan timer. start time: 2025-05-07 22:09:5…