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

接上文MIT XV6 - 1.1 Lab: Xv6 and Unix utilities - sleep

探究sleep.c是如何'炼成'的?

老实讲,我不熟悉Makefile,最多写过简单的编译和辅助脚本,拿到Xv6的Makefile是一脸懵的,至今还是一脸懵,那么我们上篇中新加的sleep.c是如何一步步的经过编译链接成一个可执行文件的?

bash 复制代码
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\

在上篇实验正文中,我们只在UPROGS 中的最后一行加了 $U/_sleep\,就能在Xv6系统的文件目录中看到一个可执行程序sleep,可是搜遍整个Makefile 文件,只有两处对他有依赖和使用

bash 复制代码
fs.img: mkfs/mkfs README $(UEXTRA) $(UPROGS)
   mkfs/mkfs fs.img README $(UEXTRA) $(UPROGS)

-include kernel/*.d user/*.d

clean: 
   rm -f *.tex *.dvi *.idx *.aux *.log *.ind *.ilg \
   */*.o */*.d */*.asm */*.sym \
   $U/initcode $U/initcode.out $K/kernel fs.img \
   mkfs/mkfs .gdbinit \
       $U/usys.S \
   $(UPROGS) \
   *.zip \
   ph barrier
  • 但是这也只是说依赖 UPROGS 啊,他在哪里编译的?在过去想要搞明白这个问题我们得去查资料,去抱大腿,甚至狠一点,从头到尾学一遍Makefile的语法规则,如今就简单多了,直接问AI,下面是cursor给我的回答

    乍一看它说的都在理,注意第三条 3. 用户程序的编译规则,仔细看这里的解释,

    这条规则的意思是:

    • 例如 _cat 依赖于 cat.o 和 $(ULIB)(用户态库)。
    • 先编译 cat.c 生成 cat.o,再和用户库链接生成 _cat 可执行文件。

这里的对于 UPROGS 里的每一个目标(如 $U/_cat),Makefile 里有如下的通用规则:中的通用规则,其实是Makefile 的一种隐藏规则,详细见 10.1 Using Implicit Rules(这也是cursor告诉我的),部分摘抄如下:

大致意思呢就是你写了foo 依赖foo.o ,但是呢又没有写规则foo.o哪里来的,那么make就会自动的去执行相关的编译.

  • 可是执行编译他怎么知道要调用gcc 并且附加上编译选项 *$(CFLAGS)*呢?这又是一条内建规则。。。原文见10.2 Catalogue of Built-In Rules

    所以,虽然这个Makefile中没有明确写 gcc user/sleep.c -o user/sleep.o,也依然通过一系列的内建规则,生成了最终的elf文件,甚至把汇编代码什么的都自动生成了。

谈一谈cursor对我的帮助

至此我想我们已经在cursor的帮助下,算是搞清楚了sleep到底是怎么得来的,他甚至还建议我你不信可以自己去验证

我还真的就去验证了

bash 复制代码
make user/sleep.o V=1
riscv64-unknown-elf-gcc -Wall -Werror -O -fno-omit-frame-pointer -ggdb -gdwarf-2 -DSOL_UTIL -DLAB_UTIL -MD -mcmodel=medany -ffreestanding -fno-common -nostdlib -mno-relax -I. -fno-stack-protector -fno-pie -no-pie -I/opt/homebrew/opt/openjdk@17/include  -c -o user/sleep.o user/sleep.c

等等,怎么有一条 -I/opt/homebrew/opt/openjdk@17/include ,这从哪里来的?继续追问

最终我查看了 我的~/.zshrc文件,果然在其中找到了定义,也再次印证了 "计算机的世界里没有魔法" 这句话

bash 复制代码
# OPENJDK
export JAVA_HOME=/opt/homebrew/opt/openjdk@17
export CPPFLAGS="-I/opt/homebrew/opt/openjdk@17/include"

我想,在如今这个时代,即使是学习晦涩难懂的底层技术原理,AI给我们带来的帮助也远超我们的想象,但如果你连问题都提不出来,他又怎么能帮你解决问题呢?所以,我们会被替代嘛?

相关推荐
加强洁西卡2 小时前
【RISC-V】riscv64-linux-gnu工具链都有哪些工具
linux·gnu·risc-v
jerwey2 小时前
RISC-V VP 中 TLM 精度
risc-v
燃于AC之乐3 小时前
【Linux系统编程】进程地址空间完全指南:页表、写时拷贝与虚拟内存管理
linux·操作系统·虚拟内存·进程地址空间
_OP_CHEN3 小时前
【Linux系统编程】(二十三)从块到块组:Ext2 文件系统核心架构的初步认识
linux·操作系统·文件系统·c/c++·ext2文件系统·磁盘分区·块组
加强洁西卡19 小时前
【RISC-V】.pushsection .popsection和.section .previous的区别
risc-v
加强洁西卡1 天前
【RISC-V】branch_test调用add_test陷入死循环的原因
risc-v
Byte不洛1 天前
Linux 多线程编程入门:线程栈、TLS、互斥锁与条件变量详解
linux·操作系统·多线程·pthread·线程互斥
_OP_CHEN1 天前
【Linux系统编程】(二十二)从磁盘物理结构到地址映射:Ext 系列文件系统硬件底层原理深度剖析
linux·操作系统·文件系统·c/c++·计算机硬件·ext文件系统·磁盘寻址
Trouvaille ~2 天前
【Linux】进程信号(三):信号捕捉与操作系统运行原理
linux·运维·服务器·c++·操作系统·信号·中断
信创天地2 天前
从 “替代” 到 “超越”:信创系统架构师如何筑牢自主可控技术底座
运维·安全·系统架构·开源·dubbo·risc-v