尧图网络 高端网站定制 · 原创设计
免费咨询热线
400-888-6620
免费获取方案
MIT 6.S081 util 实验篇(lab1):sleep (easy)
sleep (easy)实验目标本实验是 6.S081 的热身关目的不在难度而是先把手感建立起来熟悉 xv6 实验环境——git 分支怎么切、内核怎么构建、怎么运行、怎么调试、怎么评分。写出第一个用户程序sleep体会用户程序如何通过系统调用向内核请求服务。跑通评分脚本建立写代码 → 改 Makefile → 编译 → 测试这一整套开发闭环。后续所有实验都建立在这套环境之上所以这一关虽简单但不建议跳过——把工具链跑顺后面才不会被环境问题卡住。前置知识动手前先把环境和几个核心概念理清楚。1. 实验仓库结构仓库里几个文件/目录后续会反复出现路径作用kernel/操作系统内核空间源码负责底层硬件管理与系统功能实现user/用户空间应用程序源码运行在内核提供的环境之上我们写的sleep.c就放这里Makefile构建脚本用来编译出 xv6 内核与所有用户程序镜像grade-lab-xxx评分脚本完成某个小实验或整个 lab 后运行它即可打分2. 常用命令速查切换到第一个实验分支utilgitcheckout util开发与运行相关makeqemu# 构建并启动 xv6# 退出 xv6先按 Ctrla再按 xmakegrade# 给整个 lab 打分makeGRADEFLAGSsleep grade# 只测 sleep 这一个子任务util lab 中GDB 双终端调试# 终端 1以单核 gdb 方式启动 qemumakeCPUS1qemu-gdb# 终端 2连上 gdbriscv64-unknown-elf-gdb kernel/kernel3. 系统调用与 sleep 的含义sleep 实验的核心是让你第一次亲手调用一个系统调用。这一点在 xv6 手册里有明确定位。xv6 handoutChapter 1: Operating system interfaces“xv6 provides the basic interfaces—system calls, pages, files, and directories—that Unix provides.”手册系统调用一览表Figure 1-1中对 sleep 的描述是sleep(n): Pause for n clock ticks.也就是说sleep本质是一个系统调用用户程序调用它内核让当前进程挂起n个时钟滴答tick后再被唤醒。参数单位是 tickqemu 下时钟约 100Hz所以sleep 10大致暂停零点几秒实际观感因人而异把数字调大效果更明显。关键概念用户程序自己没有暂停自己的权限——能不能睡、睡多久必须由内核来裁决。这正是“系统调用 用户态请求内核服务的唯一合法入口”这个 OS 核心思想的第一个具象例子。实现思路顺着写一个命令行工具并让它真正能用的思路只需两步在user/下新建sleep.c程序需要接收一个参数要睡的 tick 数所以先检查argc是否为 2不对就打印用法并exit(1)。参数通过argv[1]传入它是字符串需要用atoi转成整数后传给sleep()。正常执行完调用exit(0)表示成功退出。在Makefile的UPROGS里注册新写的用户程序不会被自动编译进内核镜像必须手动把$U/_sleep加进UPROGS列表否则sleep命令在 xv6 里根本不存在。这一步虽小却揭示了 xv6 一个贯穿全程的套路任何用户程序 / 系统调用都要在 Makefile 里登记才能被构建。后面 labs 加新程序、新系统调用时这个动作会反复出现。代码实现user/sleep.c—— 用户态 sleep 命令/* * user/sleep.c */#includekernel/types.h#includeuser/user.hintmain(intargc,char*argv[]){if(argc!2){printf(usage: sleep ticks\n);exit(1);}sleep(atoi(argv[1]));exit(0);}几点说明sleep()和exit()的函数声明都在user/user.h里它们最终会触发ecall陷入内核所以必须包含user/user.h。argc ! 2的检查对应命令行sleep ticks恰好一个参数参数个数不对就视为用法错误返回非零退出码1。atoi(argv[1])把字符串形式的 tick 数转成整数exit(0)表示程序正常结束。Makefile—— 把程序编进内核镜像/* * Makefile */UPROGS\ $U/_cat\ $U/_echo\ $U/_forktest\ $U/_grep\ $U/_init\ $U/_kill\ $U/_ln\ $U/_ls\ $U/_mkdir\ $U/_rm\ $U/_sh\ $U/_stressfs\ $U/_usertests\ $U/_grind\ $U/_wc\ $U/_zombie\ $U/_sleep\ # 添加 $U/_sleep\验证方式一手动在 xv6 里测makeqemu# 启动 xv6进入 shell 后执行数字大一点暂停更明显sleep10观察程序是否真的暂停了相应时间再正常回到 shell 提示符。方式二用评分脚本测在 Linux 终端直接运行./grade-lab-utilsleep应看到三个子测试全部通过Test sleep, no argumentssleep, no arguments: OK(1.6s)Test sleep, returnssleep, returns: OK(0.3s)Test sleep, makes syscallsleep, makes syscall: OK(0.9s)三个测试分别验证了无参数时的健壮性、执行后能正常返回、以及确实发起了sleep系统调用。踩坑python 找不到如果运行脚本报/usr/bin/env: python: No such file or directory原因是系统里只有python3没有python。把grade-lab-util文件开头的#!/usr/bin/env python改成#!/usr/bin/env python3保存后重新执行./grade-lab-util sleep即可。后续想测 util 里的其他小实验把命令末尾的实验名换掉就行。复盘本实验解决了什么表面上只是写了 20 行代码实现一个sleep命令实际上它帮你完成了三件基础设施级别的事跑通了工具链——git 分支、make 构建、qemu 运行、gdb 调试、grade 评分这一整套环境从此不再是黑盒。建立了系统调用的第一手直觉——用户程序sleep()→ 陷入内核 → 内核让进程挂起这是你第一次亲手走完用户态请求内核服务的完整动作。记住了 xv6 的登记套路——新用户程序要在Makefile的UPROGS里注册这个动作后面会不断重复。收获什么是系统调用能讲清用户态程序没有直接操作硬件/调度进程的权限必须通过ecall之类指令陷入内核由内核代劳并返回结果——sleep 就是一个最小的例子。用户态与内核态的边界为什么sleep不能由用户程序自己while空转实现因为那样会霸占 CPU真正的挂起必须由内核从调度层面剥夺其运行权。这个问题体现了你是否对特权级和调度有基本理解。argc / argv 与程序退出码argc ! 2的用法校验、exit(0)表示成功、exit(1)表示错误是命令行工具的基本素养也是面试中 shell / 进程模型相关问题的常客。
RELATED

相关推荐

深度解读 remoteintech.company 的 Wolfram 公司档案:从 Frontmatter 到页面渲染的完整链路

深度解读 remoteintech.company 的 Wolfram 公司档案:从 Frontmatter 到页面渲染的完整链路

数据集 【免费下载链接】remote-jobs Source for remoteintech.company — a community-maintained directory of remote-friendly tech companies 项目地址: https://gitcode.com/GitHub_Trending/re/remote-jobs 点击查看 免费下载 导读 本文以开源仓库 remotei…

📅 2026/10/6 7:49:59
AWS SDK for Java 2.x 实战:Amazon ECR 仓库全生命周期管理入门场景

AWS SDK for Java 2.x 实战:Amazon ECR 仓库全生命周期管理入门场景

示例工程教程后端 【免费下载链接】aws-doc-sdk-examples Welcome to the AWS Code Examples Repository. This repo contains code examples used in the AWS documentation, AWS SDK Developer Guides, and more. For more information, see the Readme.md file below. 项目地…

📅 2026/10/6 7:49:59
深入理解 JavaScript 中 `[1]` 与 `[0]` 的 Truthiness 与隐式类型转换

深入理解 JavaScript 中 `[1]` 与 `[0]` 的 Truthiness 与隐式类型转换

文档教程知识库 【免费下载链接】til :memo: Today I Learned 项目地址: https://gitcode.com/gh_mirrors/ti/til 点击查看 免费下载 导读:在 JavaScript 中,数组作为对象永远是真值(truthy),但 [1] 和 [0…

📅 2026/10/6 7:49:59
MORE NEWS

更多资讯

📰

用最土的方式搭建AI编程助手:caveman极简方案与token优化实践

1. 项目缘起:为什么我要折腾一个叫 caveman 的东西 先说清楚 caveman 是什么。它不是一个库,也不是一个框架,更不是一个能直接 npm install 就完事的成品。caveman 是我自己给一套 AI coding agent 的最小化运行方案 起的代号。核心思路就…

📰

基尔霍夫定律失效的五大现实断点与高频修正方法

1. 为什么基尔霍夫定律不是“背公式就能用”的工具,而是电路工程师的呼吸节奏?我第一次在实验室被导师叫住,不是因为接错了线,而是因为我用万用表测完一个节点电流后,脱口而出:“KCL不就是ΣI0嘛&#xff0…

📰

串联二极管在电路中的六大作用与选型避坑指南

做硬件这些年,被问得最多的一个奇怪问题就是:“电路里串个二极管到底有啥用?”问的人往往不是刚入行的学生,就是画过几块板但没深究过细节的同事。他们看到老工程师在电源入口、信号线上随手加一颗二极管,心里犯嘀咕&a…

📰

OpenShell:打造可定制、跨平台的现代命令行环境

我们团队前阵子招了个新人,入职第一天他看到我在终端里敲命令的样子,忍不住问:“哥,你这用的什么黑科技?”当时我正在用 fzf 快速搜索一条历史命令,然后 zoxide 一键跳进项目目录,Starship 提示…

📰

电脑无法启动的硬件级排查指南:从电源到POST卡

1. 项目概述:这不是故障,是电脑在“说话”“电脑无法启动”这六个字,每年至少在我手边的维修单上出现上千次——不是服务器宕机那种惊心动魄,而是清晨赶PPT前按下电源键,屏幕一片漆黑;不是蓝屏弹窗那种明确…

📰

Vue组件通信:$refs与$parent的实战用法与避坑指南

在组件通信这个老生常谈的话题里, $refs 和 $parent 可能是最容易被低估的两个角色。很多前端开发对 props、emit 用得滚瓜烂熟,一到 $refs 和 $parent 就开始含糊:什么时候该用、什么时候不该用、拿了组件实例之后能干嘛、为什么有时…

TODAY

今日更新

THIS WEEK

本周精选

THIS MONTH

本月热门

读完文章,想聊聊您的网站?

告诉我们您的行业与需求,资深顾问一对一梳理方案与报价,全程免费。

📞 💬