libc 简介

libc 简介

2024 南京大学《操作系统:设计与实现》
libc 简介

关于 pipe() 的补充

上节课没讲清楚的细节

  • pipe read 在没有数据时会等待
  • pipe write 在有读者打开时,会写入操作系统的缓冲区并返回

pipe write() 的原子性

  • write 如果 “不太多”,一对 write-read 是原子的
  • write 如果超过 PIPE_BUF,可能会被拆成多份

RTFM: pipe (7)

  • UNIX 时代遗留的限制
2024 南京大学《操作系统:设计与实现》
libc 简介

如何读手册:效果检查

如果读者关闭,会收到 SIGPIPE 信号

  • 经常看到的 “Broken Pipe”

看见 SIGPIPE

  • “看不到” 的 SIGPIPE
    • (yes; echo $? > /dev/stderr) | head -n 1
  • “看得到” 的 SIGPIPE
    • python3 -c 'while True: print(1)' | head -n 1

类似地,“分块” 行为也可以用程序复现

2024 南京大学《操作系统:设计与实现》
libc 简介
2024 南京大学《操作系统:设计与实现》
libc 简介

系统调用是地基,C 语言是框架

C 语言:世界上 “最通用” 的高级语言

  • C 是一种 “高级汇编语言”
    • AskGPT: 为什么称 C 语言是高级的汇编语言?
    • 作为对比,C++ 更好用,但也更难移植
  • 系统调用的一层 “浅封装”

C23: 和 -frwapv 说再见!

constexpr int n = 5 + 4;  // ???
typeof(n) arr[n];  // ???

[[maybe_unused]] auto* ptr = foo();  // ???
ptr = nullptr;  // ???
2024 南京大学《操作系统:设计与实现》
libc 简介

The C Standard Library

语言机制上的运行库

  • 大部分可以用 C 语言本身实现
  • 少部分需要一些 “底层支持”
    • 例子:体系结构相关的内联汇编

库也被标准化

  • ISO IEC 标准的一部分
  • POSIX C Library 的子集
    • 稳定、可靠 (不用担心升级版本会破坏实现)
    • 极佳的移植性:包括你自己的操作系统!
2024 南京大学《操作系统:设计与实现》
libc 简介

如何 “实现” 一个 libc?

Freestanding shell 里就有一个迷你 “libc”

  • 系统调用
    • syscall
    • (通常系统调用封装成 C 函数)
  • 库函数
    • strlen, zalloc, ...
  • _start
    • “C Runtime Library”
    • -Wl,--verbose 时可以看到链接列表:Scrt1.o, crti.o, crtendS.o
2024 南京大学《操作系统:设计与实现》
libc 简介

学习已有 libc 的实现

调试 glibc?

  • 不,你不想
  • glibc 的代码有非常沉重的历史包袱
    • 以及非常多的优化——都是对 “理解原理” 的阻碍
    • 新手阅读体验极差

基本原则:总有办法的

  • 让 AI Copilot 帮你解释代码 (这个可以有)
  • 是否有比 glibc 更适合学习的 libc 实现?
    • (我承认我不如 AI)
    • 幸好我还做了正确的选择:musl
2024 南京大学《操作系统:设计与实现》
libc 简介

学习已有 libc 的实现 (cont'd)

下载源码不难,难的是怎么 “使用” 下载的 libc

  • 我们知道可以使用 gcc 和 ld
  • 到底应该用什么编译选项?

如何使用我自己的 clang、musl 替代 glibc 编译程序?

  • 当然,我们还是选择自己编译
    • 比较重要的选项
      • -O1: 减少优化级别,便于查看状态
      • -g3: 增加调试信息
    • 使用 musl-gcc 静态编译
  • 试一试:从第一条指令开始调试一个 C 程序
2024 南京大学《操作系统:设计与实现》