Skip to content

Repository files navigation

lspling

ci

lspling 是一套面向 Linux 系统编程的动手练习集,按 Robert Love 的 Linux System Programming(第 2 版)逐章、逐知识点编排。

每个练习都是一个可以独立编译和运行的 C 程序。初始文件故意保留 TODO 或错误的实现;你需要修改代码,让编译和测试通过。练习覆盖从 errno、文件描述符、缓冲 I/O,到进程、线程、信号、时间以及 GCC 扩展 的全部路径。

特性

  • 140 个练习,12 个章节:对应原书第 1 章到第 11 章和附录 A。
  • 自带测试框架:不依赖 Catch2、GoogleTest 或第三方库。
  • 自带 CLI:列出、运行、提示、查看答案、重置进度和监听文件变化。
  • 严格的编译反馈:默认使用 -Wall -Wextra -Wpedantic -Werror -Wshadow -Wformat=2, 让你习惯阅读编译器诊断。
  • 答案与初始模板分离solutions/ 保存参考答案, templates/ 保存原始练习,exercises/ 是你实际修改的目录。
  • 练习规格驱动tools/specs_*.py 是唯一的练习事实来源, 参考实现和初始练习由生成器同步。
  • 有据可依:每个练习都标注了它对应的书名小节和页码, 映射见 docs/curriculum.mddocs/knowledge-map.md

快速开始

环境要求

  • Linux(练习直接调用 Linux/POSIX 接口,如 epollinotifymremapsched_*
  • C 编译器:GCC 或 Clang(C17,POSIX 线程)
  • Python 3.8+(运行 ./lspling CLI)
  • GNU Make(可选)
  • CMake 3.20+(可选)

Debian/Ubuntu 上通常只需要:

sudo apt install build-essential python3

运行

# 查看全部练习
./lspling list

# 按章节查看
./lspling list --topic 01_file_io

# 运行下一个未完成的练习
./lspling run

# 运行指定练习(支持完整 ID、目录名或唯一后缀)
./lspling run 04_read_all
./lspling run 01_file_io/04_read_all

# 查看目标、章节出处和提示
./lspling hint 04_read_all

# 查看参考答案
./lspling solution 04_read_all

# 直接应用答案(会覆盖你的练习文件)
./lspling solution 04_read_all --apply

# 恢复初始练习
./lspling reset 04_read_all

# 监听文件变化,保存后自动重跑
./lspling watch 04_read_all

也可以使用 Makefile:

make list
make run
make verify
make selftest
make doctor
make clean

学习流程

  1. 打开书本对应章节,阅读练习目录下的 exercises/<章节>/README.md
  2. 按练习文件顶部的 objectivereferencehint 修改代码。
  3. 运行 ./lspling run <exercise>,根据编译器诊断或测试输出迭代。
  4. 卡住时先 ./lspling hint <exercise>,再看答案。
  5. 通过后进度记录在 .lspling/progress.json
  6. 完成一章后,对照 docs/knowledge-map.md 检查是否理解相关系统调用。
  7. 最后运行 ./lspling verify 验证全部参考答案,或 ./lspling selftest 检查项目自身的完整性。

练习的初始状态是刻意坏掉的:有的编译失败,有的能编译但测试失败。 这也是练习目标之一——学会根据编译器诊断和测试输出定位问题。

章节与练习

章节 主题 书本页码 练习数
1 00_introduction 系统编程基础、errno、文件与进程概念 1-24 10
2 01_file_io 文件描述符、open/read/write/lseek、select/poll 25-66 13
3 02_buffered_io 用户缓冲、标准 I/O、流锁 67-90 14
4 03_advanced_file_io readv/writev、epoll、mmap、fadvise 91-136 11
5 04_process_management fork/exec/wait、用户与组、会话 137-176 12
6 05_advanced_processes 调度、nice、亲和性、资源限制 177-210 9
7 06_threading pthread、互斥量、条件变量、取消 211-240 10
8 07_files_directories stat/chmod/xattr、目录、链接、inotify 241-292 13
9 08_memory_management 地址空间、malloc、brk、mmap、mlock 293-332 12
10 09_signals 信号处理、信号集、sigsuspend、sigqueue 333-362 12
11 10_time 时间类型、POSIX 时钟、睡眠、定时器 363-394 12
A 11_gcc_extensions typeof、属性、case 区间、指针算术 395-406 12

总计 140 个练习。完整映射见 docs/curriculum.md

项目结构

.
├── lspling                  # 零依赖 Python CLI
├── exercises/               # 你要修改的练习
│   ├── 00_introduction/
│   ├── ...
│   └── 11_gcc_extensions/
├── solutions/               # 参考答案(与 exercises 同结构)
├── templates/               # 原始练习,用于 ./lspling reset
├── include/lspling/test.h   # 自带测试框架
├── tools/
│   ├── generate_exercises.py  # 从规格生成练习/答案/模板/文档
│   ├── spec.py                # 练习规格数据结构
│   ├── specs_ch01.py ...      # 每章练习规格
│   └── specs_appendix_a.py
├── docs/
│   ├── architecture.md        # 运行器、生成器、测试框架设计
│   ├── curriculum.md          # 按章节列出全部练习(生成)
│   └── knowledge-map.md       # 按知识领域列出覆盖范围
├── .ref/                    # 参考书与提取文本(被 .gitignore 忽略)
├── CMakeLists.txt
├── CMakePresets.json
├── Makefile
└── Dockerfile

构建方式

方式一:CLI + 按需编译(推荐)

./lspling 会在需要时用系统编译器编译单个练习,构建产物放在 build/lspling/

./lspling doctor
./lspling verify
./lspling selftest

方式二:Makefile

make verify
make selftest
make check-generated

方式三:CMake + CTest

cmake --preset default
cmake --build --preset default
ctest --preset default

CMake 默认只构建 solutions/ 中的答案,并把它们注册为 CTest 测试。 初始练习使用 EXCLUDE_FROM_ALL,避免故意失败的练习阻塞整个构建。

方式四:Docker

docker build -t lspling .
docker run --rm -it -v "$PWD:/lspling" lspling ./lspling list

编译器与运行时

默认编译参数:

-std=c17 -Wall -Wextra -Wpedantic -Werror -Wshadow
-Wstrict-prototypes -Wpointer-arith -Wformat=2 -Wundef
-D_POSIX_C_SOURCE=200809L -D_DEFAULT_SOURCE -D_GNU_SOURCE -g -O0

_GNU_SOURCE 是刻意加上的:书中的 mremap()mincore()inotifymalloc_usable_size()sched_getcpu() 等 Linux 专有接口都需要它。 需要 GNU 语法(case 区间、语句表达式、void * 算术)的练习会在 文件内部用 #pragma GCC diagnostic 局部关闭对应的 pedantic 警告, 这本身也是这些练习要教的内容。

可以通过环境变量覆盖:

CC=clang ./lspling verify
CFLAGS="-fsanitize=address,undefined" ./lspling run 08_memory_management/02_malloc_and_free

如果安装了 valgrindclang-tidycppcheck,建议对内存、指针和 线程相关的章节额外运行:

valgrind ./build/lspling/08_memory_management/02_malloc_and_free.solution
clang-tidy exercises/08_memory_management/02_malloc_and_free.c -- -std=c17 -Iinclude -D_GNU_SOURCE

添加新练习

练习由 tools/specs_*.py 中的规格生成。每个规格包含正确代码、测试代码 和一组“正确片段 -> 初始片段”的替换。这样练习和答案不会不同步。

# 编辑 tools/specs_ch02.py 之类的文件
python3 tools/generate_exercises.py
./lspling verify
./lspling selftest
python3 tools/generate_exercises.py --check

注意:exercises/solutions/templates/docs/curriculum.md 都是生成产物,请改规格文件而不是改它们。

许可

项目代码使用 MIT License,见 LICENSE

参考

  • Robert Love, Linux System Programming, 2nd Edition, O'Reilly, 2013. (练习的章节划分、目标和页码引用都来自这本书)
  • clings:本项目的结构与 CLI 设计参照了同目录下的 C 语言练习集。
  • rustlings 及其衍生项目, 它们确立了“初始失败、答案通过、规格驱动”的练习集形态。
  • man 手册:man 2 introman 7 signalman 7 pthreads

About

按《Linux System Programming》(Robert Love, 2nd ed.) 逐章逐知识点编排的 140 个 Linux/POSIX 系统编程练习:规格驱动生成、零依赖 CLI、自带测试框架与参考答案。

Topics

Resources

Contributing

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages