为什么 UNIX/POSIX 系统调用命名如此难以辨认?

Ben*_*oyo 43 system-calls history posix

使用诸如 and 之类的难以理解的系统调用名称timecreat不是getCurrentTimeSecsand的原因是什么?createFile or 之,也许更适合 Unixget_current_time_secscreate_file. 这让我想到下一点:为什么有人想要cfsetospeed没有驼峰式大小写或至少下划线之类的东西以使其可读?当然,调用会有更多字符,但我们都知道代码的可读性更重要,对吗?

dr_*_*dr_ 60

这是由于当时的技术限制。POSIX标准创建于1980年代,简称UNIX,诞生于1970年。当时的几个C编译器都限制了标识符的长度为6或8个字符,从而确定了变量和函数的长度标准名称。

相关问题:

  • @phresnel:他不是在谈论文件大小、行数或语法树深度。旧版本的 C 语言确实**不**要求编译器和链接器保留多于前 31 个具有内部链接的标识符字符,*或多于 6 个外部标识符*。因此,一些早期的工具链无法区分 `get_current_date()` 和 `get_current_time()`。原因是这些系统正在处理几千字节的*微小*足迹。 (41认同)
  • 但是你说对了 `creat()`。曾有人问肯·汤普森,如果他重新设计 UNIX 系统,他会做些什么不同的事情。他的回答是:“我会用 e 拼写 creat。” (34认同)
  • @phresnel:只有有限的内存并不是硬性限制。只有有限的保证支持的标识符长度**是**。如果您只保证有 6 个重要字符,那么如果您物有所值,这就是您正在使用的。 (8认同)
  • FWIW,旧的 Fortran 标准将标识限制为 6 个字符。来自 [本书](https://books.google.com/books?id=EyujBQAAQBAJ):“一个标识符中六个字符的 Fortran 规则源于这样一个事实,即一个 IBM 704 单词可以表示六个字符。” 我不能代表 C,但我想这个限制有一个非常相似的起源(或者可能是相同的起源) (6认同)
  • 我不认为_技术约束_适用。你可以拥有大于 6 字节的文件,你可以拥有跨越数千行代码的程序;抽象语法树比六层更深,每层有更多的节点。出于某种原因,6 个字符的限制不能是技术性的,而是设计好的。并且它没有解释为什么“creat”比“create”更好。另外,你能说出你谈论的那几个C编译器吗?你的回答真的读起来像是“在某个时候听到过”。 (5认同)
  • 此外,Unix 实际上早于第一个 C 编译器——它首先用汇编语言编写,然后*重新*用 C 语言编写...;) (2认同)
  • @Petr C 函数的名称以 _ 为前缀,因此`_creat`。他仍然可以将函数命名为“create”,但可能会忽略额外的字符(尽管 IIRC 对 PDP-11 Unix 的实际限制是 8 个字符,而 6 个来自其他系统)。 (2认同)
  • @phresnel:当时的编译器/链接器/汇编器*可能*被设计为处理任意长度的标识符,但这会使用汇编语言实现它们变得更加困难,并且需要更多代码。此外,它会在编译时使用更多内存,因为编译器可能是一些运行的较大程序。(尤其是在处理具有复杂功能和大量全局变量的输入时)。因此,限制标识符长度有合理的实现原因。这比限制块嵌套或行数要少得多,因此决定。 (2认同)

Lua*_*aan 26

dr_ 是对的,但还有另一个原因 - 可用性。过去,您没有像键盘那样舒适的东西来打字。如果你幸运的话,你有一台类似于老式打字机的东西。如果你不走运,你必须处理需要实际体力工作才能运行的系统(例如,按下“键”需要很大的力),或者你手动在卡片上打孔。

这意味着即使在 6 到 8 个字符的限制内,您也尝试使命令尽可能短。这就是为什么你有ls而不是list,而creat不是create。那个时代的代码充满了变量,比如axi- 当然,x2还有朋友。打字是一项繁重的工作——今天,你打字的力度listIndex比以前“打字”要少i——而且它甚至不再那么慢(尤其是使用自动完成等附加技术)。

真正的问题是 - 为什么这么多 Unix 习语即使不再需要,仍然存在?

  • 当我的内核从`time` 变成`getCurrentTimeSecs` 或类似的东西的那一天,我就会停止升级它。即使使用我舒适的键盘和最新的硬件,这些名称仍然非常方便和简单(简单是 UNIX 的基础之一)。我真的不觉得有必要将这种 Java/C# 风格的命名带入 C 语言,更不用说在 Linux 内核中了。IMO,从内核开发人员或一般 UNIX 开发人员的角度来看,这些*习惯用法*与*不受欢迎的*完全不同。 (23认同)
  • @Benjoyo `unRootlyLongNamed.Packaged.nonsensicalFunction` 对我来说是*丑陋的*,我宁愿通过“man 2 time”来确定它的作用,而不是猜测它似乎在做什么。 (11认同)
  • @Benjoyo 好吧,*任何不习惯这种环境的人*首先不应该使用系统调用,因为它们是专门为那些习惯使用的人设计的。*(标准)库* 是为其他库提供的。UNIX 不遵循这些*时尚的设计“规则”*,因为它们乍一看很容易理解。那些*不查看任何文档*而使用它的人会遇到**很多**的麻烦,UNIX 社区中很少有人会认为这是一个需要解决的问题。 (7认同)
  • @JohnWHSmith 作为一个只编写内核驱动程序的低级开发人员,并且更喜欢不包含缩写的有意义的名称,我不同意。但这没关系,因为如果您查看原始 git 源代码,您会发现至少有一个内核开发者同意我的观点。虽然如果你告诉 Linus 他的 `get_X` 或 `remove_file_from_cache`(我可以建议 `rmfc` 吗?)对内核开发者来说是不受欢迎的,请公开这样做 - 我很乐意看到他的反应。 (7认同)
  • @JohnWHSmith 确信内核模式开发人员会知道他们的系统及其文档,但这不是没有简洁的 _and_ 名称的理由。 (4认同)
  • @JohnWHSmith:别担心,你的内核永远不会从“时间”切换到任何东西。这是因为内核不接受标识符,它接受函数调用号(在“time”的情况下,它是 13)。这些名称位于相应的头文件/用户层库中(我猜也位于内核源代码中),但不在实际的内核调用代码中;要调用内核函数,您可以使用函数编号加载特定寄存器(在 x86 上:eax),设置其他参数(通常也在寄存器中)并执行系统调用(在没有系统调用指令的系统上,通常使用软件中断) 。 (2认同)
  • @ninjalj 因为那里的每个程序都使用的函数的描述性应该特别差?如果有的话,它应该是相反的。同样,这是非常没有争议的 - 引用内核编码指南:`全局变量的描述性名称是必须的。[...] 如果你有一个计算活跃用户数量的函数,你应该称它为“count_active_users()”或类似的,你应该_不_称它为“cntusr()”。`是的,我们坚持使用旧的backcomp 的名称来自 70 年代,但对于新的 API,则使用描述性的长名称。 (2认同)

zwo*_*wol 22

除了其他答案之外,我想指出 Unix 是作为对 Multics、CTSS 和其他当代操作系统的反应而开发的,这些操作系统在命名约定方面更加冗长。您可以在http://www.multicians.org/devdoc.html 上了解这些操作系统。例如,http://www.multicians.org/mspm-bx-1-00.html给出change_name了重命名文件的命令;比较 Unix mv

此外,非常短的系统调用名称持续存在的主要原因是向后兼容性。您会注意到较新的 API 往往更加明确;例如gettimeofdayclock_gettime而不仅仅是time.

(即使在今天,在我的书中使用whateverIndex而不是ifor 循环索引是自动代码审查失败;-)

  • 是的。当 LISP 机器早于 UNIX 时,听到有关硬件功能的技术争论很有趣。当然,UNIX 机器更便宜*购买*,但仅此而已。增加维护成本(这当然不算在 *nix 领域)即使在那时也扭转了局面,但无论如何这都不是一个足够有说服力的论点。(是的,当你迭代数组时,`i` 适合作为索引。坐标?使用 `x` 和 `y`。遍历一些序数?描述性。) (2认同)

use*_*421 11

Dennis Ritchie 用 C 给自己设置了一个约束,它不依赖于 Fortran 不需要的任何链接器功能。因此,外部名称限制为 6 个字符。

  • @downvoter 你可能不同意 Denni Ritchie 的观点,但这就是他所做的。把这个答案拿出来是徒劳的。 (2认同)