ARTICLE DETAIL

资讯详情

深耕网站视觉设计与运营推广的一线实战洞察。

WSL2下CSAPP实验环境配置指南:彻底解决32位编译难题

WSL2下CSAPP实验环境配置指南:彻底解决32位编译难题 说实话看到标题里环境配置焦虑这四个字我就想起自己当年装CSAPP实验环境时的那几天。实验本身还没开始做光是让代码编译通过就耗掉了大半管精力。最崩溃的还不是报错本身而是网上的教程东一榔头西一棒子有的让装虚拟机有的说用双系统每一套方案都要折腾一晚上最后发现跟自己的Windows版本还对不上。这篇东西就是把我最终跑通的路径完整写下来Win10的原生Ubuntu子系统WSL以及CSAPP全部实验环境的一次性配置指南重点放在32位和64位库的编译问题上。内容适合刚接触CSAPP的学生、打算自学《深入理解计算机系统》的开发者、以及所有被环境配置折磨过的人。关于WSL这个方案我多说一句CSAPP的配套实验——Data Lab、Bomb Lab、Attack Lab、Cache Lab、Shell Lab、Architecture Lab——本质上全部是终端下完成的任务需要的是编译、调试、反汇编、内存检查这些能力对图形界面几乎没有任何依赖。这就让WSL变成了一个几乎为它量身定做的平台启动快、占用低、和Windows文件互通比虚拟机的体验强了不止一个档次。1. 为什么我最终选了WSL而不是双系统或虚拟机1.1 CSAPP实验究竟需要什么样的系统环境先说结论需要的是一个能运行GCC、GDB、Make、Valgrind等工具的Linux环境且需要同时支持32位和64位程序的编译运行。大部分CSAPP实验其实不挑发行版Ubuntu、Debian、CentOS都行但有个隐藏的硬性要求在前面等着你Attack Lab新版和早期版本的Buffer Lab都默认跑在32位架构下也就是说你的系统不仅要能编译64位程序还必须能编译和运行32位可执行文件。纯64位环境装完GCC后用-m32参数一编译几乎必报错这一点后面专门讲。另外Cache Lab要用Valgrind做缓存模拟和内存轨迹分析Architecture Lab需要编译Y86-64模拟器并运行汇编器Shell Lab需要大量的进程控制和信号处理。这些都是Linux下的标准工具链Windows原生环境一个都跑不起来。1.2 三种主流方案的对比我把三条路线都试过体验完全不同。方案启动速度切换成本资源占用对CSAPP适配度双系统慢需重启极高每次切换都要重启低但牺牲Windows/Linux并发使用高虚拟机VMware/VirtualBox中等中等窗口内操作高内存和CPU占用明显高但图形界面性能拖后腿WSL2秒开极低终端直接进出文件互通极低按需分配内存完全够用双系统的问题是切换的代价太高。今天CSAPP写到一半突然想起Windows里还有别的事一重启就是几分钟回来以后编译缓存也凉了。虚拟机的问题则在于资源开销VirtualBox和VMware在8G内存的笔记本上跑Ubuntu桌面版风扇转得跟飞机起飞一样而CSAPP实验其实根本不需要桌面启动一个图形界面纯粹是浪费。WSL2则完全命中需求。它没有图形界面这一层负担启动一个Ubuntu发行版只要一两秒CPU密集型的编译任务在WSL2里跑得和原生Linux几乎一样快WSL2有完整的虚拟化内核不是WSL1那种翻译层。最关键的一点Windows这边的文件可以直接被WSL访问VSCode也可以用Remote-WSL插件直接连进子系统里写代码体验接近无缝。1.3 WSL1与WSL2之间的取舍这里要区分一下WSL1和WSL2。如果你在搜索结果里看到一些老教程它们可能还在讲WSL1那是一个通过系统调用翻译实现的兼容层启动速度极快跨文件系统性能不错但对底层系统调用的支持不完整某些程序跑起来会莫名崩溃。WSL2则是真正的轻量级虚拟机运行一个完整的Linux内核系统调用100%兼容。对CSAPP实验来说这一点非常关键——Shell Lab里你可能要写大量涉及fork、execvp、waitpid、信号处理的代码WSL1的翻译层在这些敏感的系统调用上偶尔会有怪异的边界行为而WSL2不会。所以最终选择只有一个WSL2。Windows 10版本在2004及以上就能装WSL2。版本不够的话把系统更新打到最新再装Windows 10 22H2是目前最稳的版本。2. WSL2从零安装官方流程里容易被卡住的三个坑2.1 开启Windows功能与wsl --install的玄学安装WSL2的标准流程分成两步先把Windows功能打开再装发行版。第一步在PowerShell管理员里执行dism.exe /online /enable-feature /featurename:Microsoft-Windows-Subsystem-Linux /all /norestart dism.exe /online /enable-feature /featurename:VirtualMachinePlatform /all /norestart两条命令分别是开启Linux子系统和虚拟机平台第二条是WSL2能跑起来的物理基础。执行完要求重启系统别跳过这一步不重启的情况下继续安装大概率失败。第二步执行wsl --set-default-version 2把默认版本设为WSL2。然后安装Ubuntu发行版wsl --install -d Ubuntu-22.04这里就会出现很多人遇到的第一道坎wsl --install卡在半路不动或者下载速度惨不忍睹。这个问题不一定是网络问题有时候是Windows的商店组件和WSL安装器的交互出了毛病。一个实用的备选方案直接在Microsoft Store里搜索Ubuntu 22.04 LTS并点击安装。Store的下载通道和命令行走的不是同一条路径哪条快就走哪条。我自己的经历是Store明显比命令行装得快。装上以后首次启动会让你设置Linux用户名和密码这个用户名独立于Windows账户可以随便起。注意会用到root权限的命令记得加sudoUbuntu默认用户其实是在sudo组的。2.2 换源Ubuntu装好后的第一件事默认的archive.ubuntu.com源在国内的下载速度十次有九次能把人急死。装完系统的第一件事就是把apt源换成国内镜像。Ubuntu 22.04之后源配置文件的位置和格式发生了变化。旧版是编辑/etc/apt/sources.list22.04则改成了/etc/apt/sources.list.d/ubuntu.sources。打开它把URIs:那一行的地址替换成镜像站地址即可URIs: http://mirrors.aliyun.com/ubuntu/或者直接用sed替换懒得手动编辑的话先备份sudo cp /etc/apt/sources.list.d/ubuntu.sources /etc/apt/sources.list.d/ubuntu.sources.bak把其中的archive.ubuntu.com批量替换成mirrors.aliyun.com然后sudo apt update。换完源以后sudo apt full-upgrade把系统更新一遍这时候前面等待的时间成本就全都补偿回来了。2.3 路径和权限WSL里最容易走丢的地方Windows的C:\Users\YourName\Project在WSL里对应的是/mnt/c/Users/YourName/Project。很多第一次接触WSL的人会习惯性地把实验文件放在Windows侧然后在WSL里编译。这里有个重要的性能提醒/mnt/c路径下的文件跨系统访问性能比Linux文件系统差很多尤其是大量小文件操作的编译场景。你做一个编译任务可能90%的时间都浪费在跨系统文件I/O上。正确操作是把CSAPP实验文件夹放在WSL里的Linux侧比如~/csapp_labs。需要上传和下载时再通过/mnt/c中转。做Bomb Lab这类需要频繁用gdb调试的实验时文件放哪边对体验的影响极大。3. 基础工具链安装让Uban系统真正变成编译环境3.1 一键安装编译核心包进入Ubuntu后先跑一遍完整更新然后安装编译工具链。以下是一整套CSAPP实验需要的包sudo apt update sudo apt full-upgrade -y sudo apt install -y build-essential gcc g gdb make git vim sudo apt install -y gcc-multilib g-multilib libc6-dev-i386 sudo apt install -y valgrind strace binutils python3 python3-pipbuild-essential包含了GCC、G、Make和一系列基础库是所有实验的前提。gdb是Bomb Lab和Attack Lab的主角没有它你连拆炸弹的资格都没有。binutils提供objdump、readelf等反汇编工具Bomb Lab里你会反复和它们打交道。valgrind是Cache Lab的刚需用来生成和分析内存访问轨迹。3.2 补上man手册和基础开发文档一个很多人忽略但是极其重要的包manpages-dev。Shell Lab里你需要查找fork、execvp、signal、kill等系统调用的详细说明没有这个包man fork只会给你一巴掌。sudo apt install -y manpages-dev manpages-posix-dev这个细节在教程里几乎没人提但写Shell Lab的时候用处极大。别在Stack Overflow和Manpage网站之间反复横跳本地手册一秒查到才是真效率。3.3 用一个小例子验证环境装完之后验证环境是否正常。写一个简单的C程序#include stdio.h int main() { printf(CSAPP Environment OK\n); return 0; }保存为test.c然后执行gcc test.c -o test64 ./test64再来一个32位编译测试gcc -m32 test.c -o test32 ./test32如果在第二步收到一长串报错别慌这正是下一章要解决的问题。4. 32位库编译CSAPP实验最容易翻车的一环4.1 为什么CSAPP实验非要去折腾32位Attack Lab和经典版本的Buffer Lab都是构建在32位x86架构上的。原因不只是因为多年前课程设计时的历史遗留问题——32位栈布局简单直观缓冲区溢出的原理展示得更清楚对于初学者理解栈帧、返回地址、函数调用约定这些概念32位比64位友好太多了。64位体系引入了更多寄存器、更复杂的栈对齐规则和参数传递约定让你在没搞清楚基本原理之前就淹没在ABI细节里。所以课程团队宁愿保留32位的实验。这也意味着无论你的Ubuntu是64位还是arm64都必须能在用户态运行32位x86程序而安装32位运行时和编译库就是这一章的核心。4.2 gcc -m32报错背后的原理gcc -m32的意思是让GCC生成32位x86的目标代码。在x86_64的Ubuntu上要编译出32位程序编译器需要两样东西32位的头文件比如bits/libc-header-start.h32位的glibc运行库比如libc.so.6的32位版本以及在链接阶段要找的libc.so符号链接默认安装的gcc只有64位头文件和库所以当你执行gcc -m32 test.c -o test32时会在不同阶段碰到两类报错预处理或编译阶段fatal error: bits/libc-header-start.h: No such file or directory链接阶段/usr/bin/ld: cannot find -lc或/usr/bin/ld: skipping incompatible ...第一类说明缺少32位头文件第二类说明链接器找不到32位libc库。解决方式就是前面安装过的那两个包sudo apt install gcc-multilib g-multilib libc6-dev-i386gcc-multilib让GCC知道去哪里找32位版本的内部库和头文件libc6-dev-i386提供32位的libc开发文件和静态库。安装之后再跑gcc -m32一切顺畅。4.3 一个被误导的坑有时报错文件名是libc.so.6还有一类报错长这样error while loading shared libraries: libc.so.6: cannot open shared object file: No such file or directory这个不属于编译期错误而是运行期错误。它意味着编译出来的二进制文件本身是32位的但系统里缺少32位动态链接器/lib/ld-linux.so.2或者32位glibc运行库。解决方式是sudo apt install libc6-i386这个包提供32位glibc的运行库。如果你用的是较老版本的Ubuntu还可能需要lib32z1、lib32ncurses6之类的兼容库但22.04上装了libc6-i386基本够用。4.4 一个诡异的报错bash: ./dlc: No such file or directory做Data Lab时有一个必备工具dlc是老师提供的代码检查器。有同学下载后明明看到了这个文件执行时却提示No such file or directory文件权限、路径全都查过全都没问题。实际上问题出在动态链接器上。老版本的dlc是个32位动态链接的二进制如果当前Linux环境缺少32位动态链接器内核加载它的时候会直接报No such file or directory这跟文件是否存在完全没关系。执行file dlc看看输出如果是ELF 32-bit LSB executable装libc6-i386就好了。这条经验我在给同学答疑时至少救过五六个人。5. CSAPP六大实验环境逐一校验5.1 Data Labdlc和位运算检查器Data Lab是CSAPP的第一个实验要求用受限的C运算符实现一系列位操作函数。环境需求很简单GCC、Make以及官方提供的dlc检查器。把下载的实验文件解压后先进目录make clean; make。如果dlc报错参考上面的libc6-i386方案。dlc会检查你的bits.c是否使用禁止的运算符是后续实验的守门员。评分脚本driver.pl依赖perlUbuntu自带不用额外装。5.2 Bomb Labgdb就是你的主战场Bomb Lab要你通过反汇编一个二进制炸弹程序找出每个阶段的密码字符串。这个实验最吃环境的是gdb的顺手程度。我的建议是启动gdb后设置一个.gdbinit文件放在用户目录下echo set disassembly-flavor intel ~/.gdbinit echo set pagination off ~/.gdbinit第一条让反汇编显示为Intel语法比起ATT语法更适合人类阅读第二条让每次输出后不自动分页不然你在长汇编代码里翻页能翻到疯掉。查看汇编用objdump -d bomb查看字符串定位关键提示用strings bomb。binutils包已经装好直接可用。5.3 Attack Lab / Buffer Lab32位栈的现场勘查Attack Lab的环境需求比想象中要复杂一些因为ctarget和rtarget这两个可执行文件默认是64位还是32位取决于你下载的版本。新版Attack Lab的可执行文件是64位但是依然需要你写32位的注入代码或ROP链因为栈帧布局模拟的是32位时代的脆弱程序。所以它的环境要求是既能编译64位代码又有32位的运行库。如果你已经装了gcc-multilib和libc6-i386这两个条件都满足。实际操作中要注意默认壳-q参数来避免每次弹出一个不相关的评分域名查询界面./ctarget -q ./rtarget -q5.4 Architecture LabY86-64工具链和flex/bisonArchitecture Lab要求你用Y86-64汇编语言编写程序并在模拟器上运行。它自带一个sim目录里面是Y86-64处理器的模拟器源码需要自己编译。刚解压出来直接make会报错因为缺少词法分析器flex和语法分析器bison。补上sudo apt install -y flex bison然后进入sim目录执行make clean; make。稍等片刻seq目录下会生成seq-sim模拟器yas汇编器也能用了。这里要额外提醒有些版本的Architecture Lab还需要libreadline-devsudo apt install -y libreadline-dev否则编译模拟器时会出现找不到readline/readline.h的报错。5.5 Cache Labvalgrind和Python一个都不能少Cache Lab是CSAPP的第二大工程型实验分Part A和Part B。Part A要你写一个缓存模拟器csim.cPart B要做矩阵转置优化两者都要用valgrind来生成内存访问轨迹并跟你自己的模拟器对比。验证valgrind是否可用valgrind --version另外测试脚本test-csim是Python脚本需要python3。如果你连的是最小化系统的WSL记得检查python3是否安装。5.6 Shell Lab进程与信号编程的基础包Shell Lab让你用C语言写一个简单的Unix Shell涉及进程创建、信号处理、作业控制。编译所需的基础包装完就能直接用但有一个另类的环境依赖——你需要在动手写代码之前能查到各类系统调用的详细文档。manpages-dev和manpages-posix-dev在这里派上用场。写tsh.c时用man 2 fork、man 2 execvp、man 2 signal、man 2 waitpid一个终端搞定所有查阅需求。这也是这套环境配置里性价比最高的两个包。6. 我在WSL里排过的坑一次到位的避坑索引6.1 编译类报错速查表报错信息真实原因处理方式fatal error: bits/libc-header-start.h: No such file or directory缺32位头文件sudo apt install gcc-multilib/usr/bin/ld: cannot find -lc缺32位libc库sudo apt install libc6-dev-i386error while loading shared libraries: libc.so.6缺32位运行库/动态链接器sudo apt install libc6-i386bash: ./dlc: No such file or directory但文件确实存在dlc是32位二进制缺动态链接器sudo apt install libc6-i386flex: command not found缺词法分析器sudo apt install flex bisonreadline/readline.h: No such file or directory缺readline开发头文件sudo apt install libreadline-dev6.2 WSL日常使用的三条省心建议第一不要让Windows侧的杀毒软件实时扫描WSL目录。WSL2的虚拟磁盘文件本质上是ext4.vhdxWindows杀毒如果实时监控它编译时磁盘I/O开销会急剧上升。把%LOCALAPPDATA%\Packages\CanonicalGroupLimited*路径加入杀毒排除列表后编译速度肉眼可见地提升。第二用VSCode的Remote-WSL插件。在Windows侧装好VSCode装上Remote-WSL扩展然后在WSL终端里执行code .VSCode会自动启动并连接子系统。这样写代码时用的是Linux侧的编译环境API提示、头文件解析全部正确。第三关于字体。在WSL终端里写代码字体默认的Consolas在等宽对齐上不算差但Cascadia Code的连字特性能把-、等符号渲染得更有层次感。Windows Terminal里把配置文件字体改成Cascadia Code阅读汇编代码和多级指针时的舒适度会上升不少。还有一个空间问题顺带解决WSL2的虚拟磁盘文件不会随着你在Linux侧删文件而自动缩小。如果你大量操作过实验文件发现Windows侧的磁盘空间没释放在PowerShell里执行wsl --shutdown然后找到虚拟磁盘文件路径打开diskpart执行select vdisk file...和compact vdisk。做一次可以回收几个GB的空间。这些坑我基本都是逐个踩过才总结出来的。环境配好了后面做实验的专注度完全不一样——至少当报错弹出来时你能确认是代码的问题而不是环境的问题。至于从哪一步开始做实验我的建议永远是从Data Lab开始那是所有实验里最温柔的一个入门点能让你快速适应这套工具链。
返回列表