Skip to content

Instantly share code, notes, and snippets.

@FrankHB
Last active August 15, 2016 15:48
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save FrankHB/78f8145abb357e8440228811998455c4 to your computer and use it in GitHub Desktop.
Save FrankHB/78f8145abb357e8440228811998455c4 to your computer and use it in GitHub Desktop.
UNIX/POSIX烂设计

糟糕的设计审计和接口设计质量

例如几乎没什么用的文件锁

综合示例

sem_open 允许 EINTR ,凭空制造 race condition ,根本没法确定打开时是不是同时创建了信号量。

而文件系统持久语义导致不 sem_unlink 就会在最后/进程挂掉以后遗留空的信号量(如果权限设置有问题后面访问/创建同名的信号量都麻烦)。

而要是提前 sem_unlink 对新进程又根本起不到命名信号量的作用了。

信号

有许多本不必要的麻烦是(异步)信号导致的。这种和体系结构密切相关的特性在 C 的层次上显式指定,导致接口难以使用,极易出错。

由于并非常用,经常得不偿失。

直接劣化接口设计、增加使用成本的普遍典型例子是 EINTR

这也导致了需要考虑特定的异步信号安全性,显著增加了标准化和用户使用的成本。

任务控制

fork

烂 userland 实现导致 resource leak 还要 UI 层次上干掉不够坑么,到底谁的锅甩给谁算是正义的?都怪应用开发者太笨?

当然, fork 作为系统调用层次的存在就导致一坨烂设计了。(整体的系统调用有一大坨问题倒是可以单独挂婊 Linux 而不是 BSD ,但这和这里说的无关。)

烂的理由

首先 forkNtCreateProcess 少了一坨参数这点很多时候更方便,这是对的。(至于拿 CreateProcess 去比的逗用户就不用说了。)

但渣就渣在它返回了 pid_t ,而 pid_t 和实际占用的资源又莫名其妙多了一个间接层,导致本来不需要担心去多管的资源( pid_t 或者说 process table entry )会因为应用(父进程)以及系统实现自身的 bug 而莫名泄漏。后面糊上 SA_NOCLDWAIT 已经为时过晚。

仔细想想, pid_t 这玩意儿存在的意义是什么?除去 shell 这样纯粹可以限制只在 userland 考虑的东西,根本毫无卵用。结果就是让整个设计变脏了同时让用户付出莫名其妙的代价。

或者仅仅是设计者一开始脑补哲学和万行码的故事所以对此视而不见?锅甩给应用开发者甚至最终用户倒是挺溜的嘛。呵呵。

其次提供接口的层次性有明显不逻辑的不协调之处,以至于经常不符合日常需求。

对多数的普遍的需求,往 fork 上糊 exec 也是明显二的做法;而实现上也不讨好。于是不得不糊了个 vfork 。这仍然是个变通。

然而为什么不一开始就提供 spawn ?鬼知道。

第三是上面问题暴露出来的 fork 本身功能粒度都成问题。

我特么宁可参数多点,好歹先把用户要做的描述清楚了。

想想随便一个什么语言提供 default constructor 和往 default constructor 糊补丁实现状态复制(或者所谓的 copy constructor )会是怎么样的场景?

为什么不一开始就提供 rfork/clone

即便是这样,脑补一坨 task_struct 剩下甩锅的做法也不见得就聪明。

特别地,和上面本质上是目无进程资源边界的 pid_t 的锅一样,很多本应该由任务控制擦完屁股的东西扔给用户空间去糊,搞得线程实现乌烟瘴气(嗯,当然还有传统上的辣鸡信号的一大坨锅,不过这也与这里说的没直接关系)。能更二点么。

第四是依赖于页面内存管理这种硬件抽象层以下实现细节的 leaking abstraction 诱发更严重的普遍幼稚假设导致的问题。

其中比较明显的是以为钦定写时复制而放任 overcommit ,不提前限制配额而是搞出 OOM killer 擦屁股,最后直接坑死不知所谓的最终用户。这锅甩得敢再溜点么。

其实用依赖不可禁用的 GC 的运行时搭建整个应用框架(没错,再挂挂 Android),无视能够容易保守估计的资源边界,自以为“充分利用资源”和这里倒是很有异曲同工之妙。只不过更恶劣的是不像 OOM killer 一样作为了 last sorted feature 来用。讽刺的是,多亏 Android 改了传统 Linux 内核处理的 low memory conditions 的驱动,才有机会稍微干净点把 Android 不管用户需求靠瞎蒙策略乱杀进程的不检点行为给绕过去……可惜也治不了绕过这个不得门而入反而没下限去改 Android 框架代码开后门的一些烂定制系统了。

文件系统

还有一大口锅是所谓的文件系统,也就是比 Web 正确了那么一点点。暂时不展开了。

其它

其实很多传统上的设计问题当年 ESR 就提过了,虽然他看样子不是很擅长理清是不是 userland 的锅。

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment