[translated] 20181112 The Source History of Cat

This commit is contained in:
name1e5s 2018-12-08 23:10:59 +08:00
parent 1df5f8e3cc
commit 3482daca7a
2 changed files with 94 additions and 95 deletions

View File

@ -1,95 +0,0 @@
Name1e5s translating.
The Source History of Cat
======
I once had a debate with members of my extended family about whether a computer science degree is a degree worth pursuing. I was in college at the time and trying to decide whether I should major in computer science. My aunt and a cousin of mine believed that I shouldnt. They conceded that knowing how to program is of course a useful and lucrative thing, but they argued that the field of computer science advances so quickly that everything I learned would almost immediately be outdated. Better to pick up programming on the side and instead major in a field like economics or physics where the basic principles would be applicable throughout my lifetime.
I knew that my aunt and cousin were wrong and decided to major in computer science. (Sorry, aunt and cousin!) It is easy to see why the average person might believe that a field like computer science, or a profession like software engineering, completely reinvents itself every few years. We had personal computers, then the web, then phones, then machine learning… technology is always changing, so surely all the underlying principles and techniques change too. Of course, the amazing thing is how little actually changes. Most people, Im sure, would be stunned to know just how old some of the important software on their computer really is. Im not talking about flashy application software, admittedly—my copy of Firefox, the program I probably use the most on my computer, is not even two weeks old. But, if you pull up the manual page for something like `grep`, you will see that it has not been updated since 2010 (at least on MacOS). And the original version of `grep` was written in 1974, which in the computing world was back when dinosaurs roamed Silicon Valley. People (and programs) still depend on `grep` every day.
My aunt and cousin thought of computer technology as a series of increasingly elaborate sand castles supplanting one another after each high tide clears the beach. The reality, at least in many areas, is that we steadily accumulate programs that have solved problems. We might have to occasionally modify these programs to avoid software rot, but otherwise they can be left alone. `grep` is a simple program that solves a still-relevant problem, so it survives. Most application programming is done at a very high level, atop a pyramid of much older code solving much older problems. The ideas and concepts of 30 or 40 years ago, far from being obsolete today, have in many cases been embodied in software that you can still find installed on your laptop.
I thought it would be interesting to take a look at one such old program and see how much it had changed since it was first written. `cat` is maybe the simplest of all the Unix utilities, so Im going to use it as my example. Ken Thompson wrote the original implementation of `cat` in 1969. If I were to tell somebody that I have a program on my computer from 1969, would that be accurate? How much has `cat` really evolved over the decades? How old is the software on our computers?
Thanks to repositories like [this one][1], we can see exactly how `cat` has evolved since 1969. Im going to focus on implementations of `cat` that are ancestors of the implementation I have on my Macbook. You will see, as we trace `cat` from the first versions of Unix down to the `cat` in MacOS today, that the program has been rewritten more times than you might expect—but it ultimately works more or less the same way it did fifty years ago.
### Research Unix
Ken Thompson and Dennis Ritchie began writing Unix on a PDP 7. This was in 1969, before C, so all of the early Unix software was written in PDP 7 assembly. The exact flavor of assembly they used was unique to Unix, since Ken Thompson wrote his own assembler that added some features on top of the assembler provided by DEC, the PDP 7s manufacturer. Thompsons changes are all documented in [the original Unix Programmers Manual][2] under the entry for `as`, the assembler.
[The first implementation][3] of `cat` is thus in PDP 7 assembly. Ive added comments that try to explain what each instruction is doing, but the program is still difficult to follow unless you understand some of the extensions Thompson made while writing his assembler. There are two important ones. First, the `;` character can be used to separate multiple statements on the same line. It appears that this was used most often to put system call arguments on the same line as the `sys` instruction. Second, Thompson added support for “temporary labels” using the digits 0 through 9. These are labels that can be reused throughout a program, thus being, according to the Unix Programmers Manual, “less taxing both on the imagination of the programmer and on the symbol space of the assembler.” From any given instruction, you can refer to the next or most recent temporary label `n` using `nf` and `nb` respectively. For example, if you have some code in a block labeled `1:`, you can jump back to that block from further down by using the instruction `jmp 1b`. (But you cannot jump forward to that block from above without using `jmp 1f` instead.)
The most interesting thing about this first version of `cat` is that it contains two names we should recognize. There is a block of instructions labeled `getc` and a block of instructions labeled `putc`, demonstrating that these names are older than the C standard library. The first version of `cat` actually contained implementations of both functions. The implementations buffered input so that reads and writes were not done a character at a time.
The first version of `cat` did not last long. Ken Thompson and Dennis Ritchie were able to persuade Bell Labs to buy them a PDP 11 so that they could continue to expand and improve Unix. The PDP 11 had a different instruction set, so `cat` had to be rewritten. Ive marked up [this second version][4] of `cat` with comments as well. It uses new assembler mnemonics for the new instruction set and takes advantage of the PDP 11s various [addressing modes][5]. (If you are confused by the parentheses and dollar signs in the source code, those are used to indicate different addressing modes.) But it also leverages the `;` character and temporary labels just like the first version of `cat`, meaning that these features must have been retained when `as` was adapted for the PDP 11.
The second version of `cat` is significantly simpler than the first. It is also more “Unix-y” in that it doesnt just expect a list of filename arguments—it will, when given no arguments, read from `stdin`, which is what `cat` still does today. You can also give this version of `cat` an argument of `-` to indicate that it should read from `stdin`.
In 1973, in preparation for the release of the Fourth Edition of Unix, much of Unix was rewritten in C. But `cat` does not seem to have been rewritten in C until a while after that. [The first C implementation][6] of `cat` only shows up in the Seventh Edition of Unix. This implementation is really fun to look through because it is so simple. Of all the implementations to follow, this one most resembles the idealized `cat` used as a pedagogic demonstration in K&R C. The heart of the program is the classic two-liner:
```
while ((c = getc(fi)) != EOF)
putchar(c);
```
There is of course quite a bit more code than that, but the extra code is mostly there to ensure that you arent reading and writing to the same file. The other interesting thing to note is that this implementation of `cat` only recognized one flag, `-u`. The `-u` flag could be used to avoid buffering input and output, which `cat` would otherwise do in blocks of 512 bytes.
### BSD
After the Seventh Edition, Unix spawned all sorts of derivatives and offshoots. MacOS is built on top of Darwin, which in turn is derived from the Berkeley Software Distribution (BSD), so BSD is the Unix offshoot we are most interested in. BSD was originally just a collection of useful programs and add-ons for Unix, but it eventually became a complete operating system. BSD seems to have relied on the original `cat` implementation up until the fourth BSD release, known as 4BSD, when support was added for a whole slew of new flags. [The 4BSD implementation][7] of `cat` is clearly derived from the original implementation, though it adds a new function to implement the behavior triggered by the new flags. The naming conventions already used in the file were adhered to—the `fflg` variable, used to mark whether input was being read from `stdin` or a file, was joined by `nflg`, `bflg`, `vflg`, `sflg`, `eflg`, and `tflg`, all there to record whether or not each new flag was supplied in the invocation of the program. These were the last command-line flags added to `cat`; the man page for `cat` today lists these flags and no others, at least on Mac OS. 4BSD was released in 1980, so this set of flags is 38 years old.
`cat` would be entirely rewritten a final time for BSD Net/2, which was, among other things, an attempt to avoid licensing issues by replacing all AT&T Unix-derived code with new code. BSD Net/2 was released in 1991. This final rewrite of `cat` was done by Kevin Fall, who graduated from Berkeley in 1988 and spent the next year working as a staff member at the Computer Systems Research Group (CSRG). Fall told me that a list of Unix utilities still implemented using AT&T code was put up on a wall at CSRG and staff were told to pick the utilities they wanted to reimplement. Fall picked `cat` and `mknod`. The `cat` implementation bundled with MacOS today is built from a source file that still bears his name at the very top. His version of `cat`, even though it is a relatively trivial program, is today used by millions.
[Falls original implementation][8] of `cat` is much longer than anything we have seen so far. Other than support for a `-?` help flag, it adds nothing in the way of new functionality. Conceptually, it is very similar to the 4BSD implementation. It is only longer because Fall separates the implementation into a “raw” mode and a “cooked” mode. The “raw” mode is `cat` classic; it prints a file character for character. The “cooked” mode is `cat` with all the 4BSD command-line options. The distinction makes sense but it also pads out the implementation so that it seems more complex at first glance than it actually is. There is also a fancy error handling function at the end of the file that further adds to its length.
### MacOS
In 2001, Apple launched Mac OS X. The launch was an important one for Apple, because Apple had spent many years trying and failing to replace its existing operating system (classic Mac OS), which had long been showing its age. There were two previous attempts to create a new operating system internally, but both went nowhere; in the end, Apple bought NeXT, Steve Jobs company, which had developed an operating system and object-oriented programming framework called NeXTSTEP. Apple took NeXTSTEP and used it as a basis for Mac OS X. NeXTSTEP was in part built on BSD, so using NeXTSTEP as a starting point for Mac OS X brought BSD-derived code right into the center of the Apple universe.
The very first release of Mac OS X thus includes [an implementation][9] of `cat` pulled from the NetBSD project. NetBSD, which remains in development today, began as a fork of 386BSD, which in turn was based directly on BSD Net/2. So the first Mac OS X implementation of `cat` is Kevin Falls `cat`. The only thing that had changed over the intervening decade was that Falls error-handling function `err()` was removed and the `err()` function made available by `err.h` was used in its place. `err.h` is a BSD extension to the C standard library.
The NetBSD implementation of `cat` was later swapped out for FreeBSDs implementation of `cat`. [According to Wikipedia][10], Apple began using FreeBSD instead of NetBSD in Mac OS X 10.3 (Panther). But the Mac OS X implementation of `cat`, according to Apples own open source releases, was not replaced until Mac OS X 10.5 (Leopard) was released in 2007. The [FreeBSD implementation][11] that Apple swapped in for the Leopard release is the same implementation on Apple computers today. As of 2018, the implementation has not been updated or changed at all since 2007.
So the Mac OS `cat` is old. As it happens, it is actually two years older than its 2007 appearance in MacOS X would suggest. [This 2005 change][12], which is visible in FreeBSDs Github mirror, was the last change made to FreeBSDs `cat` before Apple pulled it into Mac OS X. So the Mac OS X `cat` implementation, which has not been kept in sync with FreeBSDs `cat` implementation, is officially 13 years old. Theres a larger debate to be had about how much software can change before it really counts as the same software; in this case, the source file has not changed at all since 2005.
The `cat` implementation used by Mac OS today is not that different from the implementation that Fall wrote for the 1991 BSD Net/2 release. The biggest difference is that a whole new function was added to provide Unix domain socket support. At some point, a FreeBSD developer also seems to have decided that Falls `raw_args()` function and `cook_args()` should be combined into a single function called `scanfiles()`. Otherwise, the heart of the program is still Falls code.
I asked Fall how he felt about having written the `cat` implementation now used by millions of Apple users, either directly or indirectly through some program that relies on `cat` being present. Fall, who is now a consultant and a co-author of the most recent editions of TCP/IP Illustrated, says that he is surprised when people get such a thrill out of learning about his work on `cat`. Fall has had a long career in computing and has worked on many high-profile projects, but it seems that many people still get most excited about the six months of work he put into rewriting `cat` in 1989.
### The Hundred-Year-Old Program
In the grand scheme of things, computers are not an old invention. Were used to hundred-year-old photographs or even hundred-year-old camera footage. But computer programs are in a different category—theyre high-tech and new. At least, they are now. As the computing industry matures, will we someday find ourselves using programs that approach the hundred-year-old mark?
Computer hardware will presumably change enough that we wont be able to take an executable compiled today and run it on hardware a century from now. Perhaps advances in programming language design will also mean that nobody will understand C in the future and `cat` will have long since been rewritten in another language. (Though C has already been around for fifty years, and it doesnt look like it is about to be replaced any time soon.) But barring all that, why not just keep using the `cat` we have forever?
I think the history of `cat` shows that some ideas in computer science are very durable indeed. Indeed, with `cat`, both the idea and the program itself are old. It may not be accurate to say that the `cat` on my computer is from 1969. But I could make a case for saying that the `cat` on my computer is from 1989, when Fall wrote his implementation of `cat`. Lots of other software is just as ancient. So maybe we shouldnt think of computer science and software development primarily as fields that disrupt the status quo and invent new things. Our computer systems are built out of historical artifacts. At some point, we may all spend more time trying to understand and maintain those historical artifacts than we spend writing new code.
If you enjoyed this post, more like it come out every two weeks! Follow [@TwoBitHistory][13] on Twitter or subscribe to the [RSS feed][14] to make sure you know when a new post is out.
--------------------------------------------------------------------------------
via: https://twobithistory.org/2018/11/12/cat.html
作者:[Two-Bit History][a]
选题:[lujun9972][b]
译者:[译者ID](https://github.com/译者ID)
校对:[校对者ID](https://github.com/校对者ID)
本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
[a]: https://twobithistory.org
[b]: https://github.com/lujun9972
[1]: https://github.com/dspinellis/unix-history-repo
[2]: https://www.bell-labs.com/usr/dmr/www/man11.pdf
[3]: https://gist.github.com/sinclairtarget/47143ba52b9d9e360d8db3762ee0cbf5#file-1-cat-pdp7-s
[4]: https://gist.github.com/sinclairtarget/47143ba52b9d9e360d8db3762ee0cbf5#file-2-cat-pdp11-s
[5]: https://en.wikipedia.org/wiki/PDP-11_architecture#Addressing_modes
[6]: https://gist.github.com/sinclairtarget/47143ba52b9d9e360d8db3762ee0cbf5#file-3-cat-v7-c
[7]: https://gist.github.com/sinclairtarget/47143ba52b9d9e360d8db3762ee0cbf5#file-4-cat-bsd4-c
[8]: https://gist.github.com/sinclairtarget/47143ba52b9d9e360d8db3762ee0cbf5#file-5-cat-net2-c
[9]: https://gist.github.com/sinclairtarget/47143ba52b9d9e360d8db3762ee0cbf5#file-6-cat-macosx-c
[10]: https://en.wikipedia.org/wiki/Darwin_(operating_system)
[11]: https://gist.github.com/sinclairtarget/47143ba52b9d9e360d8db3762ee0cbf5#file-7-cat-macos-10-13-c
[12]: https://github.com/freebsd/freebsd/commit/a76898b84970888a6fd015e15721f65815ea119a#diff-6e405d5ab5b47ca2a131ac7955e5a16b
[13]: https://twitter.com/TwoBitHistory
[14]: https://twobithistory.org/feed.xml
[15]: https://twitter.com/TwoBitHistory/status/1051826516844322821?ref_src=twsrc%5Etfw

View File

@ -0,0 +1,94 @@
The Source History of Cat
======
以前我和我的一些亲戚争论过计算机科学的学位值不值得读。当时我正在上大学,并要决定是不是该主修计算机。我姨和我一表姐觉得我不应该主修计算机。她们承认知道如何编程肯定是很有用且对自己有利的一件事,但是她们认为计算机科学现在发展的如此迅速以至于我学的东西几乎马上就过时了。建议我更好是把编程作为辅业,选择一个基础原理可以受用终身的领域主修,比如经济学或物理学。
我知道我姨和我表姐说的不对,并决定主修计算机科学。(对不住啊!)平常人可能会觉得像计算机科学领域和软件工程专业每隔几年就完全和之前不一样了。其原因很容易理解。我们有了个人电脑,然后有了互联网,有了手机,之后还有了机器学习…… 科技总是在更新,支撑科技发展的原理和技能当然也在改变。当然,最惊人的是其实原理的改变竟然如此之小。我敢肯定,大多数人在知道了他们电脑里一些重要的软件的历史是多么久远时他们一定会深感震惊。当然我不是说那些刷版本号的浮夸软件 —— 我电脑上的 Firefox 浏览器副本,可能是我用的最多的软件,可能才更新不到两周。如果你看了比如 `grep` 的手册页,你就会发现他在 2010 年后就没有过更新了(至少在 MacOS 上如此)。初版 `grep` 是在 1974 年写就的,那时可以算是计算机世界的侏罗纪了。直到现在,人们(还有程序)仍然依赖 `grep` 来完成日常工作。
我姨和我表姐认为计算机技术就像一系列日渐精致的沙堡,在潮水抹净沙滩后新的沙堡完全取代旧的。但事实上,在很多领域上,我们都是不断积累能够解决问题的程序。我们可能不得不偶尔修改这些程序以避免软件无法使用,但大多数情况下我们都可以不修改。 `grep` 是一个简单的程序,可以解决一个仍然存在的问题,所以它能够存活下来。 大多数应用程序编程都是在非常高的级别上完成的,他们建立在解决了旧问题的程序的金字塔上。 30年或40年前的想法和概念远非过时在很多情况下他们依然在您的笔记本电脑上软件中存在着。
我想追溯这样的老程序自第一次写就以来改变了多少回很有趣。 `cat`可能是所有 Unix 实用程序中最简单的,因此我们以它为例。 Ken Thompson于 1969 年编写了 `cat` 的原始实现。如果我告诉别人我的电脑上安了个 1969 年的程序,这准确吗?我们电脑上的程序多大了?
感谢这种[这种][1]仓库,我们可以完整的看到 `cat` 自 1969 年后是如何发展的。我会先聚焦于可以算得上是我的 MacBook 上的 `cat` 的祖先的 `cat` 实现。随着我们从 Unix 上的第一版 `cat` 追踪到现在 MacOS 上的 `cat`,你会发现,这个程序被重写的次数比你想的还要多 —— 但是直到现在它运行的方式和五十年前多少是完全一致的。
### 研究 Unix
Ken Thompson 和 Dennis Ritchie 在 PDP 7 上开始写 Unix。那还是 1969 年C 还没被发明出来,因此所有早期的 Unix 软件都是用 PDP 7 汇编实现的。他们使用的汇编种类是 Unix 特有的Ken Thompson 在 DEC也就是 PDP 7 的厂商提供的汇编器之上加了些特性实现了自己的汇编器。Thompson 的更改在[最初的 Unix 程序员手册][2]的 `as`(也就是汇编器)条目下均有所记录。
因此,[最初的][3] `cat` 也是使用 PDP 7 汇编实现的。 我添加了一些注释,试图解释每条指令的作用,但除非你理解 Thompson 在编写汇编器时加的特性,否则程序仍然很难理解。在那些特性中有两个很重要:其一是 `;` 这个字符可以在一行中用来分隔多条语句,它多出现于在使用 `sys` 指令时将系统调用的多个参数放在同一行上。其二是, Thompson 的汇编器支持使用 0 到 9 作为“临时标签”,也就是在程序内可以重用的标签。因此。就如 Unix 程序员手册中所说:“对程序员的想象力和汇编程序的符号空间的要求都降低了”。在任何给定的指令内,你都可以使用 `nf``nb` 来引用下一个或最近的临时标签 `n`。 例如,如果存在标记为 `1:` 的代码块,你就可以使用指令 `jmp 1b` 从下游代码跳回该块。 (但是你不使用 `jmp 1f` 的话就没法从上面的代码跳到这里。)
初版 `cat` 最有趣的就是它包含着我们应该认识的符号。有一块指令快标记为 `getc`,还有一个标记为 `putc`,可以看到这两个符号比 C 标准还古老。第一版的 `cat` 函数实际上已经包含了这两个函数的实现。这个 `cat` 实现做了缓存,这样他就不需要一次只读写一个字母。
`cat` 的第一个版本并没有持续多久。 Ken Thompson 和 Dennis Ritchie 说服贝尔实验室购买了 PDP 11这样他们就能够继续扩展和改进 Unix。 PDP 11 的指令集和之前不一样,因此必须重写 `cat`。 我也注释了[这个第二版][4] `cat`。 它为新的指令集使用新的汇编程序助记符,并利用了 PDP 11 的各种[寻址模式][5]。(如果你对源代码中的括号和美元符号感到困惑,那是因为这些符号用于指示不同的寻址模式。)但它也使用 `;` 字符和临时标签,和 `cat` 的第一个版本一样,这意味着当把 `as` 移植到 PDP 11 上时,必须要保留这些功能。
`cat` 的第二个版本比第一个版本简单得多。 它也更有 Unix 味儿,它不只是依靠参数列表,一旦没给参数列表,它将从 `stdin` 读取数据,这也就是今天 `cat` 仍在做的事情。 你也也可以在此版本的 `cat` 中以 `-` 为参数,以表示它应该从`stdin`读取。
在 1973 年,为了准备发布第四版 Unix大部分代码都用 C 语言重写了。但是 `cat` 似乎在之后一段时间内并没有使用 C 重写。 [`cat` 的第一个 C 语言实现][6]出现在第七版 Unix 中。 这个实现非常有趣,因为它很简单。 在所有要以后的实现中,这个实现和在 KR 的 C语言教科书中用作教学示范的理想化 `cat` 最相似。这个程序的核心就是经典的两行:
```
while ((c = getc(fi)) != EOF)
putchar(c);
```
当然实际代码要比这多一些,额外的代码主要是为了确保你没有在读/写同一个文件。另一个有趣的事情是,`cat` 的这一版实现只识别一个标志位 `-u``-u` 标志可用于避免缓冲输入和输出,否则 `cat` 将以 512 字节为块进行输入输出。
### BSD
在第七版之后Unix 出现了了各种衍生品和分支。 MacOS 建立于 Darwin 之上,而 Darwin 又源自 Berkeley Software DistributionBSD因此 BSD 是我们最感兴趣的Unix 分支。 BSD 最初只是 Unix 中的实用程序和附加组件的集合,但它最终成为了一个完整的操作系统。直到第四版 BSD人称 4BSD为一大堆新标志添加了支持之前BSD 似乎还是依赖于最初的 `cat` 实现的。`cat` 的 [4BSD 实现][7] 显然是从原始实现中衍生出来的,尽管它添加了一个新函数来实现新标志触发的行为。按照已经在文件中使用由用于标记输入是从`stdin`还是文件读取的 `fflg` 变量指定的命名约定。被新添加的 `nflg``bflg``vflg``sflg``eflg`和`tflg` 保存了下来,这些变量记录了在调用程序时是否使用了这些新标志。这些是最后一批添加到 `cat` 的命令行标志。如今 `cat` 的手册页列出了这些标志没有其他的标志了至少在Mac OS上是如此。 4BSD 于1980年发布因此这套标志已有 38 年历史。
`cat` 最后一次被完全重写是在 BSD NET/2 上,其目的是通过替换全部 AT&T 发布的 Unix 源代码来规避许可证问题。BSD Net/2 在 1991 年发布。这一版本的 `cat` 是由 Kevin Fall 重写的。 Kevin Fall 于 1988 年毕业于加州大学伯克利分校并在下一年成为计算机系统研究组CSRG的组员Fall 和我说当时使用 AT&T 代码的 Unix 工具被列在了 CSRG 的墙上,组员需要从中选出他们想要重写的工具; Fall 选了 `cat` 以及 `mknod`。 MacOS 系统内自带的 `cat` 实现源码的最上面还有着他的名字。他的这一版 `cat`,尽管平淡无奇,在今天还是被无数人使用着。
[Fall的原始 `cat `实现][8] 比我们迄今为止看到的程序都要长。 除了支持 `-?` 帮助标志外,它没有增加任何新功能。 从概念上讲,它与 4BSD 的实现非常相似。 它长是因为 Fall 将实现分为 “原始” 模式和 “熟” 模式。 “原始” 模式是 `cat ` 的经典实现; 它一个字符一个字符的打印文件。 “熟” 模式是带有所有 4BSD 命令行选项的 `cat`。 如此区别不无道理,但这么办也扩充了实现规模,因此乍一看其源码似乎比实际上更复杂。文件末尾还有一个奇特的错误处理函数,进一步地增加了实现的长度。
### MacOS
在 2001 年,苹果发布了 MacOS X。这一发布对苹果意义重大。因为苹果花了很多年时间来尝试并且取代现有的过时操作系统经典的Mac OS但是都失败了。 在 Mac OS X 之前苹果两次尝试在内部创建一个新的操作系统,但两者都无疾而终。 最后,苹果收购了史蒂夫 · 乔布斯的 NeXT 公司,后者开发了一个名为 NeXTSTEP 的操作系统和面向对象编程框架。 苹果将 NeXTSTEP 作为Mac OS X的基础。因为 NeXTSTEP 部分基于 BSD使以 NeXTSTEP 为基础的 Mac OS X的自然就把 BSD 系的代码直接带入苹果宇宙的中心。
因此Mac OS X的第一个版本包含了从 NetBSD 项目中提取的 `cat` 的[实现][9]。如今仍在开发中的 NetBSD 最初是 386BSD 的分支,而后者又直接基于 BSD Net/2。所以Mac OS X里面的第一个 `cat` 的实现就是 Kevin Fall的 `cat`。唯一改变的是Fall 的错误处理函数 `err()``err.h` 提供的`err()` 函数取代了。 `err.h` 是 C 标准库的 BSD 扩展。
之后不久,`cat` 的 NetBSD 实现被换成了 FreeBSD 中的 `cat` 实现。 [根据维基百科][10]苹果在Mac OS X 10.3(Panther) 中开始使用 FreeBSD 的实现而不是 NetBSD 的实现。但根据苹果自己开源的版本,`cat` 的Mac OS X实现在2007年发布的 Mac OS X 10.5(Leopard) 之前没有被替换。苹果为 Leopard 替换的的 [FreeBSD 实现][11]与今天苹果计算机上的实现相同。截至 2018 年,此实现仍未被更新或修改。
所以Mac OS 上的 `cat` 已经很老了。实际上,这一实现在 2007 年在 MacOS X 上露面两年前就被发布了。 [这个 2005 年的修改][12] 在 FreeBSD 的 Github 镜像中可见,是在苹果将其合并入 Mac OS X 前对 FreeBSD 的 `cat` 实现进行的最后一次更改。所以 Mac OS X 的没有与 FreeBSD 的 `cat` 实现保持同步的 `cat`实现,如今 13 岁了。对于软件修改了多少代码才能仍是算是同一软件这一话题有着旷日持久的争论。不过,在这种情况下,源文件自 2005 年以来根本没有变化。
现在 Mac OS 使用的 `cat` 实现与 Fall 1991年为 BSD Net/2 版本编写的实现没有什么不同。最大的区别是添加了一个全新的功能来提供 Unix 域套接字支持。FreeBSD 开发人员似乎将 Fall 的 `raw_args()` 函数和 `cook_args()` 函数组合成一个名为`scanfiles()`的函数。要没有的话,程序的核心就仍是 Fall 的代码。
我问过 Fall 对编写如今被数以百万计的苹果用户直接或者通过依赖 `cat` 的程序间接使用的 `cat` 实现有何感想。Fall如今是最新版 TCP/IP 详解的顾问和合著者,说,当人们从了解他对 `cat` 所做的的工作中收获颇丰时,他感到很惊讶。 Fall 在计算机领域有着悠久的职业生涯,曾参与许多备受瞩目的项目,但似乎很多人仍对他在 1989 年重写 `cat` 的那六个月的工作感到最为兴奋。
### 百年老程序
在宏伟的发明史中,计算机并不是一项古老的发明。我们已经习惯了百年的照片甚至是百年的视频短片。但是计算机程序不一样 - 它们代表着高科技和新技术。至少,他们是现代的技术造出来的。随着计算行业的成熟,我们有朝一日会发现自己正在使用有着接近百年历史的程序吗?
计算机硬件可能会发生较大的变化,使得我们也许无法让现在编译的可执行文件在一个世纪后的硬件上运行。也许编程语言设计的进步让未来没有人能理解 C 语言,`cat` 将来也可能也被别的语言重写很久了。 (尽管 C已经存在了五十年了而且它似乎不会很快就被替换掉。但除此之外为什么不永远使用我们现在的 `cat`
我认为 `cat` 的历史表明,计算机科学中的一些想法确实非常持久。事实上,对于 `cat`,这个想法和程序本身都很古老。不准确地说,我的电脑上的 `cat` 来自1969 年。但我也可以说我的计算机上的 `cat` 来自1989 年,当时 Fall 写了他的 `cat` 实现。许多其他软件也同样古老。因此,也许我们不应该把计算机科学和软件开发视为不断破坏现状和发明新事物的领域。我们的计算机系统是由诸多历史文物构建的。有时,我们可能会花费更多时间在理解和维护这些历史文物上,而不是花在编写新代码上。
如果你喜欢本文,你可能更喜欢两周来一篇更新!在推特上关注 [@TwoBitHistory][13] 或者订阅这个 [RSS 源][14] 以保证接受到新的文章。
--------------------------------------------------------------------------------
via: https://twobithistory.org/2018/11/12/cat.html
作者:[Two-Bit History][a]
选题:[lujun9972][b]
译者:[name1e5s](https://github.com/name1e5s)
校对:[校对者ID](https://github.com/校对者ID)
本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
[a]: https://twobithistory.org
[b]: https://github.com/lujun9972
[1]: https://github.com/dspinellis/unix-history-repo
[2]: https://www.bell-labs.com/usr/dmr/www/man11.pdf
[3]: https://gist.github.com/sinclairtarget/47143ba52b9d9e360d8db3762ee0cbf5#file-1-cat-pdp7-s
[4]: https://gist.github.com/sinclairtarget/47143ba52b9d9e360d8db3762ee0cbf5#file-2-cat-pdp11-s
[5]: https://en.wikipedia.org/wiki/PDP-11_architecture#Addressing_modes
[6]: https://gist.github.com/sinclairtarget/47143ba52b9d9e360d8db3762ee0cbf5#file-3-cat-v7-c
[7]: https://gist.github.com/sinclairtarget/47143ba52b9d9e360d8db3762ee0cbf5#file-4-cat-bsd4-c
[8]: https://gist.github.com/sinclairtarget/47143ba52b9d9e360d8db3762ee0cbf5#file-5-cat-net2-c
[9]: https://gist.github.com/sinclairtarget/47143ba52b9d9e360d8db3762ee0cbf5#file-6-cat-macosx-c
[10]: https://en.wikipedia.org/wiki/Darwin_(operating_system)
[11]: https://gist.github.com/sinclairtarget/47143ba52b9d9e360d8db3762ee0cbf5#file-7-cat-macos-10-13-c
[12]: https://github.com/freebsd/freebsd/commit/a76898b84970888a6fd015e15721f65815ea119a#diff-6e405d5ab5b47ca2a131ac7955e5a16b
[13]: https://twitter.com/TwoBitHistory
[14]: https://twobithistory.org/feed.xml
[15]: https://twitter.com/TwoBitHistory/status/1051826516844322821?ref_src=twsrc%5Etfw