解码的GNU Coreutils:探索GNU公用事业的设计

2021-03-11 01:02:39

这是一个长期的项目,用于解码版本8.3中的所有GNU Coreutils。

此资源用于探索命令行实用程序设计的新手程序员。它最好用作提供有用背景的伴奏,同时阅读您可能感兴趣的实用程序的源代码。这不是用户指南 - 有关使用这些实用程序的说明,请参阅适用的人页面。

状态:完成! 阶段1 [完成] - 每个实用程序都有一个专用页面讨论命名空间和执行概述。

第2阶段[完整] - 扩展了关于重要设计决策和算法的探讨。从UNIX和早期COREUTILS进行跟踪效用谱系。将内容移植到更协作的内容。增强源演练以更有用的东西。创建源代码Evolution Visualizer

阶段无限线通过线路代码行演进,每用实用程序将在很长一段时间内完成。 github repo可用于收集逐行的笔记。由于一致反馈,读者对高级讨论更感兴趣,这段部门被推迟。

I' ll将实用程序页面链接到顶部。单击命令名称有关解码该实用程序的详细页面的命令名称。每个页面都可以使用讨论,源代码和演练。粗体公用事业已被扩展为阶段2.享受!

GNU Coreutils有其披风。许多这些公用事业都在进行30岁,多年来包括许多人的修订。以下是阅读代码时要记住的一些事情: 微小的程序 - 这些实用程序很小,(大多数)单源文件程序,旨在做一件事并做得好。它们不是设计长寿或超越其角色。因此,我们看到经常考虑的设计'糟糕的练习'如:

了解POSIX - 从实用程序语法准则开始。通常,POSIX通过定义适当的输入和输出来支持互操作性,但留下'工作'实施。虽然GNU Coreutils可能无法严格符合POSIX,但许多想法都是根本的:权限位,UID / GID,环境变量,退出状态以及大约3718页的更多琐事。

外部帮助 - 可移植性是一个复杂的问题,Coreutils依赖于相关项目的额外帮助:Gnulib。几乎每个实用程序都包括来自Gnulib的功能,专门为各种系统中许多地方使用的常见问题而设计 - 无需重新发明轮子。

从shell启动 - 核心实用程序希望从Bash,Zsh,Ksh等壳牌等支持。 Shell fors / clones进入实用程序,通过参数,设置环境,通过管道重定向I / O,并保留退出值。

三个家庭 - GNU Coreutils最初是壳牌,文本和文件实用程序的三个不同的套餐。同一类型中的实用程序共享许多相同的设计模式。

这是框架i' ll用于组织每个实用程序的解码。我们' LL看到每个人都有一个独特的变体,从几行到数千行。 D分为三组中的变体:琐碎,包装器和完整的公用事业

琐碎的公用事业 琐碎的实用程序有一个唯一的设置阶段,它定义了几条线的宏。然后'包括'宏强制特定流量控制的另一个实用程序的来源。示例包括:arch,dir和vdir

包装工具 包装器执行设置和解析命令行选项,该选项将直接作为参数传递给syscall。 Syscall的结果是该实用程序的结果。这些公用事业公司自行处理。示例包括:链接,whoami,hostId,logname等

全部公用事业 上图显示了用于完整实用程序的设计。设置阶段,选项/参数解析阶段和执行。执行意味着处理输入数据,并且可以沿着处理更多数据的方式调用许多SYSCALL,直到完成。大多数公用事业都属于此类别。

让'我们经历了许多公用事业共享的最常见的想法。事先知道这些概念应该加快代码阅读。

initialize_main(& argc,& argv); set_program_name(argv [0]); setlocale(lc_all,""); BindTextDomain(包,Localedir); 侄子(包); atexit(close_stdout);

该序言解决了一些行政问题;其中最重要的是国际化和分配退出行动。我' ll下面穿过这些线条。这条线不会影响效用的具体行动。

曾经想过为什么指挥线公用事业公司在过去的40年里有同样的外观和感觉?您可以感谢getopt工具集。你需要知道的最小值遵循coreutils是:

命令行选项可以是'短'和#39;长',分别以( - )和( - )为前缀。当长选项使用结构时,短选项定义为字符串。

短选项使用1)如果选项没有参数,则只有一个字母,2)对于强制参数,一个单个冒号(:),和(::)用于可选参数。例如,kill的短选项字符串是:lln:s:t。这说L,L,T没有参数,但是n和s需要一个论点。

UNIX的系统通常支持FTS库以轻松管理通过文件系统的步行。基本的手摇细节是:

树由通过在路径上调用fts_open()或xfts_open()构建的FTS结构表示。

ftsent-> fts_info字段描述了条目。它经常用于决定如何处理该条目。

Coreutils经常通过包装纸和借口来调用Syscalls,超出Libc提供的那些。许多人通过gnulib项目链接。

libc提供了许多文本编写功能,例如fwrite(),用于缓冲流访问,以及Write()Syscall包装器。 Coreutils带来了Full_Write()等非标准函数。除非存在困难故障,否则Full_Write()函数连续重试写入。它依赖于safe_write()来重试跨中断的写入()syscall。其他写入相关的助手仅在单个实用程序中使用。如DD,CWRITE()中的IWRITE()。我' ll讨论公用事业中的人。

使用()函数显示包含输入参数,其含义和适当语法列表的实用程序的帮助。

_()函数真的是系统中定义的宏,它在gnu getText.h中将简单的语言支持功能绑定到母语支持功能。如果它' s字符串意味着向用户展示,它可能会用这个函数包裹。

#include" system.h" 此标题定义了系统相关的MarcoS,变量和有用的非标准函数。它提供'翻译和#39;必要的是让Coreutils尽可能多地构建。总的来说,这个标题是缺乏严重组织的角落案件的拼凑 - 但它有效!此标题中包含许多C标准和POSIX标头,例如:unistd.h,limits.h,ctypes.h,time.h,string.h,errno.h,stdbool.h,stdlib.h,fcntl.h,fcnt.h ,inttypes.h和locale.h。

#define program_name" cat" 定义实用程序的官方名称。用于'版本'查看。

#define authors perfect_name("理查德M. Stallman") 定义实用程序的作者。用于'版本'查看。

emit_try_help() 在输出失败后打印帮助建议。包括与在线文档的链接。这将出现在使用开始()

emit_ancillary_info(program_name) 在命令特定输出后打印常见的额外帮助信息。包括与在线文档的链接。这似乎接近使用结束()

退出(状态) Syscall将使用给定状态结束执行。这在使用结束时出现()

initialize_main(& argc,& argv) 用于VM的特殊处理程序强制内置通配符扩展。这是对大多数其他操作系统的定义

set_program_name(argv [0]); 使用第一个输入参数保存基本程序名称。丢弃ARGV的路径分量[0]。

atexit(close_stdout); 在程序结束时注册Close_stdout函数以进行调用。除了关闭外,这刷新了缓冲蒸汽。

if_lint(某事); 如果使用包括宫内内的代码,请抑制GCC警告如果使用LINTER。通常这是nop

在Coreutils来源中有一些习语可能是初学者不熟悉的。 ! 双重惊吓点正是您所看到的,双重无需操作。目的是强迫一个霸勃的价值。它常用于函数返回值的标志。

do {...} while(0) 非循环通常包含多语句宏,以确保在预处理器替换后正确令牌化。核心用例是结果: 请注意,在C代码中宏后手动添加半冒号缺乏半冒号。

Coreutils等活动项目总是在不断发展。通常,更新继续三个弧:

项目范围内更改 - 这些是对所有公用事业的基础架构和依赖性的更大规模。一些亮点包括: 1995年:通过GNU GetText项目增加了母语支持。这在大多数文本输出线周围并入了_()宏。国际化支持于1996年扩展,将几个初始化者添加到主()中,如前一节所述

2016:Die()宏将大多数Exit()和错误()函数替换为故障路径的函数,以避免编译器警告

实用程序特定更新 - 许多更改仅适用于子集或单个实用程序。这些案例通常分为三类:错误修复,新功能和优化。每种类型的示例包括:

BUG:加入,排序和UNIQ命令易于溢出攻击,直到2016年修补

年度维护 - 至少,所有公用事业公司的版权年份都会更新。另一个管理变更包括更新FSF地址。这些变化对执行没有影响

对于好奇的读者,我包括一个'进化'在每个实用程序页面中的视图以可视化实用程序随时间的变化。

有兴趣的人应该在GNU项目页面上阅读所有内容。拒绝特征的贡献指南和列表尤为开悟。最后,通过邮件列表档案来了解最有价值的贡献。在编写任何代码之前需要考虑的很短的清单:

Veteran开发商寻找偷看这些公用事业公司的理由可能希望在这里开始旅程。

最短的实用程序:假(2行 - 与Arch,Dir和Vdir绑定) 最短独立实用程序:真实(80行) - 第一个版本几乎是最低的C程序! 最长的效用:LS(5308线)

许多公用事业在20世纪70年代追溯到研究UNIX。甚至进一步回到多个

最古老的精神祖先是CTSS listf命令(〜1963)。谢天谢地短暂到LS DD实用程序的独特语法是请联想到OS / 360职能控制语言(20世纪60年代初)。

DF实用程序比du更快。前者使用设备元数据,而后者检查所有文件

cksum包括两个入口点,一个用于正常操作,一个用于生成CRC-32表

我的个人最不使用的公用事业是Tsort和PTX - 我在20世纪90年代后期测试了一次

好的项目!我如何捐出以支持这项努力? 谢谢你的想法;不幸的是,我没有被配置为获得个人捐款。但随时与自由软件基金会分享您的时间或金钱 - 以及所有合作努力发生的地方!