Skip to content

病在哪儿:-1 是个什么都能装的筐

先给你看个场景。你写了个用户程序,调 read(),内核返回 -1。然后呢?是文件读到尾了(EOF)?盘 IO 出错了?文件根本不存在?你没权限?——-1 把这四件完全不同的事揉成了一个数,你对着日志里一句 [SYS_MKDIR] failed 干瞪眼,不知道下一步该查哪。

这一章治两件越往后越扎手的事。第一,给内核的错误一个名字、一个类型——ErrorOr,让"出错了"不再是含糊的 -1,而是"什么错"。第二,把散在内核各处、东一份西一份的公共类型(StringViewSpanRingBufferCRC32…)收进一个共享库 Cinux-Base,别再每个子系统自己造一遍。这两件是后面文件系统、多进程、网络那些大特性的地基——地基不夯实,越往上晃得越厉害。

先看清病:-1 是个什么都能装的筐

在只有只读 ext2 + 单进程 shell 的小体量下,"出错返 -1、调用方看着办"勉强够用——出错路径就那么几条,-1 大致等于"没找到 / 读崩了 / 你给错了"三合一。可一旦系统要长大,这套就崩了。三个具体的疼:

三态歧义。 int read(...) 这个返回值,-1 是错、0 是 EOF、正数是字节数。调用方得记着这套不成文的约定,稍不留神就把 EOF 当成错误处理了。

错误信息丢了。 -1 不会告诉你"没找到"还是"盘崩了"还是"权限不够"。排查时日志只剩一句含糊的失败,对着猜。

类型不帮你。 -1 是个 int,编译器没法在你忘了检查错误时提醒你。它就是个普通的返回值,你爱忽略就忽略,忽略了就把一个错误值一路传进文件系统深处,某天炸在一个莫名其妙的地方。

这三疼,根源是同一个:错误没有身份。它只是个约定俗成的数,没有名字、没有类型、没有"非处理不可"的强制性。

035_multi_terminal-45-gf25de18 · f25de18 · 2026-08-04