2011-03-28 18:09:00 suizhuhebi 阅读数 164

      《Unix编程艺术》这本书是我看过的计算机类书中最能引起我共鸣的书,也是我认为最好最经典的一本Unix系统参考书。Unix曾和C语言一起传播到世界,它曾经历百花齐放的时代,它也承载着太多的分流与衍生。《Unix编程艺术》是一种思想的阐述,是一种大的宏观的实践工作需要,有时候在Unix操作,那些小巧实用的工具让工作轻松不已,Unix系统多么的善解人意。
      本书主要介绍了Unix系统领域中的设计和开发哲学、思想文化体系、原则与经验,由公认的Unix编程大师、开源运动领袖人物之一Eric S. Raymond倾力多年写作而成。包括Unix设计者在内的多位领域专家也为本书贡献了宝贵的内容。本书内容涉及社群文化、软件开发设计与实现,覆盖面广、内容深邃,完全展现了作者极其深厚的经验积累和领域智慧。少一点技术,多一些共享文化:显见和隐微的,直观和潜流的——这是本书和大多数Unix书籍不同的地方:不止于方法,更重乎理念。
      虽然自己不是Unix程序员,但是Unix的好多理念其实早就脱离Unix本身,这一点也是感受颇深的。这本书确实有关‘知识’,但更着眼于‘专能’,可能入门和理解的难度偏高,比较适合有一定的编程经验的人。读过了,领会了,其实一切都那么简单,说它可以作为有经验者的良师益友实在是不为过。
      

2011-09-10 11:07:10 jeson1130 阅读数 187
 <Unix编程艺术>
1.数据压倒一切。如果已经选择了正确的数据结构并且把一切都组织得井井有条,

  正确的算法也就不言自明。编程的核心是数据结构,而不是算法。

2.在设计中,应该主动将代码的复杂度转移到数据之中去。

3.优雅的代码不仅将算法传达给计算机,同时也把见解和信心传递给阅读代码的人

4.不要让调试工具仅仅成为一种事后追加或者用过就束之高阁的东西。它们是通往

   代码的窗口:不要只在墙上凿出粗糙的洞,要修整这些洞并装上窗。如果打算让代

   码一直可被维护,就始终必须让光照进去。

5.如果希望让代码成为活代码,则最有效的时间花费方法之一就是投入精力使代码

  具备可维护性(并以此吸引未来的维护者)。

6. 尽可能少干活,让数据塑造代码;依靠工具,把机制从策略中分离。专家级unix

   程序员要学会迅速自动的看出这些可能性。建设性的懒惰是大师级程序员的基本

   美德之一。

7.更一般地,阅读代码是为未来投资。可以从中学到甚多---新技术,分解问题的新

  方法,不同的风格和手段。使用代码和学习代码都能得到有价值的回报。即使并不

  使用所研究代码中的方法,学习他人解决方案中改良的问题定义,也许能够帮助自

  己发现一个更好的方法。


  写之前先读,培养阅读代码的习惯。很少有什么彻底全新的问题,所以几乎总是能

  够发现非常接近的代码,成为自己需要的一个良好起点。即使当问题真正非常新颖

  时,也很有可能与某人之前已经解决的问题相关,而解决方案也很可能是从某个已

  经存在的方案发展而来。

2015-06-06 16:47:50 vonzhoufz 阅读数 831

《Unix编程艺术》读书笔记(1)


这两天开始阅读该书,下面是自己的体会,以及原文的摘录,虽然有些东西还无法完全吃透。

写优雅的代码来提高软件系统的透明性:(P134)

Elegance is a combination of power and simplicity. Elegant code does much with little. Elegant code is not only correct but visibly, transparently correct. It does not merely communicate an algorithm to a computer, but also conveys insight and assurance to the mind of a human that reads it. By seeking elegance in our code, we build better code. Learning to write transparent code is a first, long step toward learning how to write elegant code — and taking care to make code discoverable helps us learn how to make it transparent. Elegant code is both transparent and discoverable.

调试工具是通往代码内部的窗口,能够发现大多数的bug:(P139)

The lesson is this: Don’t let your debugging tools be mere afterthoughts or treat them as throwaways. They are your windows into the code; don’t just knock crude holes in the walls, finish and glaze them. If you plan to keep the code maintained, you’re always going to need to let light into it.

GCC编译器是一个关于透明性的很好的实例,它能通过命令行清晰的揭示出预处理器,汇编器,连接器等各个组件的具体工作流,中间结果很有用:P(140)

the driver program has monitoring switches that merely (but sufficiently) expose the textual data flows among the components.

要追求代码的透明,就是不要在具体操作的代码之上叠放太多的抽象层,保持薄胶合层:P149

If you want transparent code, the most effective route is simply not to layer too much abstraction over what you are manipulating with the code.

批评了过度的面向对象,既要模块化编程,也要保持着地,而不是站的离基本组件太高(不同的语言应该有所侧重??):P150

Unix programmers are the original zealots about modularity, but tend to go about it in a quieter way. Keeping glue layers thin is part of it; more generally, our tradition teaches us to build lower, hugging the ground with algorithms and structures that are designed to be simple and transparent.

透明性和可显性,与模块性一样,是软件系统的设计特性,而不是代码的编码风格,难有特定的硬性规定,需要思考:P150

  • What is the maximum static depth of your procedure-call hierarchy? That is, leaving out recursions, how many levels of call might a human have to model mentally to understand the operation of the code? Hint: If it’s more than four, beware.
  • Does the code have invariant properties that are both strong and visible? Invariant properties help human beings reason about code and detect problem cases.
  • Are the function calls in your APIs individually orthogonal, or do they have too many magic flags and mode bits that have a single call doing multiple tasks? Avoiding mode flags entirely can lead to a cluttered API with too many nigh-identical functions, but the obverse error (lots of easily-forgotten and confusable mode flags) is even more common.
  • Are there a handful of prominent data structures or a single global scoreboard that captures the high-level state of the system? Is this state easy to visualize and inspect, or is it diffused among many individual global variables or objects that are hard to find?
  • Is there a clean, one-to-one mapping between data structures or classes in your program and the entities in the world that they represent?
  • Is it easy to find the portion of the code responsible for any given function? How much attention have you paid to the readability not just of individual functions and modules but of the whole codebase?
  • Does the code proliferate special cases or avoid them? Every special case could interact with every other special case; all those potential collisions are bugs waiting to happen. But even more importantly, special cases make the code harder to understand.
  • How many magic numbers (unexplained constants) does the code have in it? Is it easy to discover the implementation’s limits (such as critical buffer sizes) by inspection?

隐藏细节和无法访问细节有着重要区别,优秀的程序员应该给程序设定调试标志和探测开关,看开源代码,这一点很常见,debug选项,可以透视程序的运行状态。P151

Programs that cannot reveal what they are doing make troubleshooting far more difficult. Thus, experienced Unix users actually take the presence of debugging and instrumentation switches as a good sign, and their absence as possibly a bad one. Absence suggests an inexperienced or careless developer; presence suggests one with enough wisdom to follow the Rule of Transparency.

将软件系统划分为协作进程,虽全局复杂度降低,但是代价是需要合适的进程间通信协议,接口部分都是bug的聚集地,还需要为通信各方设计状态机,真正重要的不是协议语法而是协议逻辑(模型的正确性)。P159

The real challenge is not protocol syntax but protocol logic—designing a protocol that is both sufficiently expressive and deadlock-free. Almost as importantly, the protocol has to be seen to be expressive and deadlock-free; human beings attempting to model the behavior of the communicating programs in their heads and verify its correctness must be able to do so.

这里翻译的不好理解,应该理解为popen只能为shellout搭建输入或则输出管道,但是却不能构建双向管道,因为pipe是单向的。P168

Unix’s popen(3) call can set up either an input pipe or an output pipe for a shellout, but not both for a slave process — this seems intended to encourage simpler programming.

信号IPC的一种常用场景是pidfile,进程A把自身的PID写入到一个普通的文件中,在以后的某个时候进程B可以据此文件对A进行控制,如kill它。P171

A technique often used with signal IPC is the so-called pidfile. Programs that will need to be signaled will write a small file to a known location (often in /var/run or the invoking user’s home directory) containing their process ID or PID. Other programs can read that file to discover that PID. The pidfile may also function as an implicit lock file in cases where no more than one instance of the daemon should be running simultaneously.

SIGHUP信号通常作为守护进程重新载入配置文件的信号。P172

Many well-known system daemons accept SIGHUP (originally the signal sent to programs on a serial-line drop, such as was produced by hanging up a modem connection) as a signal to reinitialize (that is, reload their configuration files); examples include Apache and the Linux implementations of bootpd(8), gated(8), inetd(8), mountd(8), named(8), nfsd(8), and ypbind(8).

虽然文本流没有经典的RPC性能高,但是系统简单,易于理解,XML-RPC/json-rpc综合了二者的优点。P179

Even if text streams were less efficient than RPC, the performance loss would be marginal and linear, the kind better addressed by upgrading your hardware than by expending development time or adding architectural complexity. Anything you might lose in performance by using text streams, you gain back in the ability to design systems that are simpler — easier to monitor, to model, and to understand.

线程共享地址空间,暴漏了彼此太多的内部状态,所以产生了竞争问题。而进程有独立的地址空间,良好的封装,通过明确的IPC进行通信。而且,在多线程中的时序依赖也是一个很难的问题。P180

Threads are a fertile source of bugs because they can too easily know too much about each others’ internal states. There is no automatic encapsulation, as there would be between processes with separate address spaces that must do explicit IPC to communicate. Thus, threaded programs suffer from not just ordinary contention problems, but from entire new categories of timing-dependent bugs that are excruciatingly difficult to even reproduce, let alone fix.

2018-09-26 22:49:50 u013830320 阅读数 38

第一部分 上下正文

第一章.哲学

文化?什么文化?

这一本有关于Unix编程的书籍,但是我们反复提到’文化’,'艺术’和’哲学‘。如果你不是一个程序员,或你是一位很少接触过Unix的程序员,对这些词语可能奇怪。然而Unix有一种文化,它具有一种独特的编程艺术;文化承载着一种强有力的设计哲学。理解这些传统文化会帮助你构建出更好的软件,即使你不在Unix平台上开发。

每种工程设计分支都有技术文化。在大多数工程领域中,这个领域不成文文化与(随着经验增长,甚至更重要)官方手册和教科书一样重要,这种文化成为从业人教育的一部分。高级工程师发展出大量的隐性知识,这些知识通过(正如佛教禅宗所说的)“经文之外的一种特殊传播”传递给下级。

软件工程通常对这种规则是一种例外,技术改变的非常快,软件环境来的快,消失的也快。技术文化是很脆弱的和短暂的。然而对于这个例外是有例外的。很少的软件技术能够持久地发展强有力的技术文化,独特的艺术和代代工程师传承的相关设计理念。

Unix文化就是其中之一。互联网文化是另一种文化,或者在21世纪,可以说是同一种文化。从1980初以来,这两种文化越来越难分离,在这本书中我们不会特别努力去分开的。

Unix的持久性

Unix诞生于1969年,从那时开始连续的生产使用。以行业标准来看,这是几个地质时代,比PC、工作站、微型处理器、甚至视频显示终端还要老,和第一个半导体存储器同时出现。在如今所有生产分时系统中,仅有IBM的VM/CMS可以声称存活的时间更长,Unix机器可以提供成百上千倍服务时间,实际上,Unix可能支持比所有其他分时系统加起来还要多的计算。

相比其他操作系统,Unix在更广泛的机器上得到应用。从超计算机到手持设备和嵌入式网络硬件,通过工作站、服务器、PC和小型计算机,Unix可能比其他三种操作系统加起来都还要多体系结构和更多的古怪的硬件。

Unix支持令人难以置信的广泛使用。没有任何其他操作系统能同时作为研究工具、技术定制应用程序的友好主机、商用现成商业软件的平台和互联网的重要组成部分技术而闪耀。

自从Unix诞生以来,每年有人满怀信心的预测,Unix会枯萎,或者被其他操作系统排挤出去。然而,Unix,在它今天的化身中,如Linux、BSD、Solaris和MacOS X以及其他六个变种,似乎比今天更强。

至少Unix的核心技术之一—C语言–已经在其他地方广泛的使用。实际上很难想象没有C作为普遍存在的系统编程语言来进行软件工程。Unix也引入了无处不在的树形文件名称空间和目录节点、已经连接程序的管道。

Unix的耐久性和适应性令人震惊。其他技术像蜉蝣样来来去去。机器的能力已经提高了千倍,语言在改变,行业实践已经经历多次变革–并且Unix仍然存在,依然在生产,支付订单,仍然赢得了地球上许多最好、最聪明软件技术专家的忠诚。

计算能力与时间的指数曲线以及软件开发的相应的速度所带来的后果之一是,人们所知道的东西50%会在每18个月就会过时。Unix并没有消除这个现象,但是在包含这种现象方面做的很好。

唯有不变的基础–语言、系统调用、工具调用–可以使用多年,甚至几十年。在其他地方,不可能预测什么是稳定的,甚至整个操作系统停止使用。在Unix下,瞬时知识和长久知识之间有相当明显的不同,人们可以提前知道(大约90%都是确定的),当他们学习时,什么东西可能会落到哪个类别。因此就是Unix 命令。

Unix的稳定性和成功在很大程度上归功于其固有的优势,这要归功于Ken Thompson、Dennis Ritchie、Brian Kernighan、Doug McIlroy、Rob Pike以及早期Unix开发人员在一开始所做的设计决策;一遍又一遍被证明是正确的决定。但这也要归功于早期围绕Unix发展起来的设计理念、编程艺术和技术文化。从那以后,这个传统就一直在与Unix的共生关系中成功地传播着。

反对学习Unix文化的案例

Unix耐久性和技术文化当然是那些已经喜欢Unix感兴趣的,同时也是技术历史学家感兴趣的。但是Unix最初作为中型和大型计算机的分时操作系统的应用程序正在迅速退出历史迷雾,被个人工作站所消灭。对被微软主导的主流商业桌面市场上,微软能取得成功还是有怀疑的空间。

局外人常常把Unix当作学术玩具或黑客的沙箱而不屑一顾。一个著名的论战,Unix Hater者的手册》(加芬克尔),遵循一个敌对的Unix本身一样古老,在写它的信徒崇拜的宗教狂和输家。当然,AT&T、Sun、Novell以及其他商业供应商和标准协会在错误定位和错误营销Unix方面一再犯的巨大错误已经成为传奇。

甚至从Unix世界内部来看,Unix似乎在普遍性的边缘徘徊了很长一段时间,以至于人们怀疑它永远不会真正实现它。一个持怀疑态度的外部观察者的结论可能是,Unix太有用而不能消亡,但太笨拙而不能从后面的房间里跳出来;一个永久的操作系统。

最让怀疑论者困惑的是Linux和其他开源的unix(如现代的BSD变种)的兴起。事实证明,Unix的文化非常重要,即使十年来供应商管理不善也无法遏制它。今天,Unix社区本身已经控制了技术和营销,并且正在迅速而明显地解决Unix的问题(我们将在第20章更详细地研究这种方法)。

Unix出了什么问题

对于可以追溯到1969的一个设计来说,在Unix中识别明显错误的设计选择是非常困难的。有个几个很受欢迎的候选方案,但是每个都仍然是激烈辩论的主题,不仅仅在Unix爱好者之间,而且在思考设计操作系统的更广泛群体中也是如此。

Unix文件没有超过字节级的结构。文件删除是不可撤销的。Unix的安全模型可以说太原始。工作控制太拙劣。事物有太多种类的名称。拥有一个文件系统是一个错误的选择。我将在20章讨论这些技术问题。

但是,这个对Unix最持久反对可能是它的一个理念的特性的结果,这个特性最初由X窗口系统设计者明确提出。X努力提供机制,不是策略,支持一组非常通用的图像操作,并将有关工具包和界面外观(策略)的决策推迟到应用级别。Unix的其他系统级别服务也显示出类似的趋势,最终行为的选择被尽可能推向用户。Unix用户可以在多个shell中进行选择。Unix程序通常提供许多行为选项和精心设计的首选工具。

这中趋势反映了Unix作为主要为技术用户设计的操作系统的传统,并且用户比操作系统设计人员更了解他们自己的需求。

但是机制-非策略方法的代价是,当用户可以设置策略时,用户必须设置策略。非技术用户经常发现Unix丰富的选项和接口风格势不可挡,并退回到至少假装提供简单性系统中。

在短期内,Unix的自由放任方法可能会失去很多非技术用户。然而,从长期来看,这种“错误”可能会带来一个关键的优势——因为政策的寿命往往很短,而机制往往很长。今天界面外观的时尚常常成为未来进化的死胡同(使用过时的X工具包的人会告诉你一些感觉!)因此,另一方面,“机制,而不是策略”哲学可能使Unix能够在竞争者更多地将其联系在一套策略上或已经从人们视野退化的界面选择之后很久,Unix才更新了它的相关性。

2017-05-16 16:43:00 weixin_30556959 阅读数 10


下载地址:网盘下载


内容简介  · · · · · ·

作者简介  · · · · · ·

《The Art of UNIX Programming》,简称TAOUP,作者Eric S. Raymond,简称ESR。这大概是计算机类书籍中很少见的一本课外读物。TCP/IP编程之类典型Unix编程书中讲到的东西在这本书里面找不到,所以书里讲到的当然就是别的书里找不到的东西。读者也许需要有相当的Unix背景、或者长期钻研某个专题,才能体会到作者的弦外之音。ESR作为老牌黑客信手拈来的典故,如果不是在Unix里面长期浸淫,大概很难有所共鸣,所以把这当作Unix的一部坊间史话倒也合适。

目录  · · · · · ·

序 xxv
part i 1
第1章 哲学 3
1.1 文化?什么文化 3
1.2 unix的生命力 4
1.3 反对学习unix文化的理由 5
1.4 unix之失 6
1.5 unix之得 7
1.5.1 开源软件 7
1.5.2 跨平台可移植性和开放标准 8
1.5.3 internet和万维网 8
1.5.4 开源社区 9
1.5.5 从头到脚的灵活性 9
1.5.6 unix hack之趣 10
1.5.7 unix的经验别处也可适用 11
1.6 unix哲学基础 11
1.6.1 模块原则:使用简洁的接口拼合简单的部件 14
1.6.2 清晰原则: 清晰胜于机巧 14
1.6.3 组合原则:设计时考虑拼接组合 15
1.6.4 分离原则: 策略同机制分离,接口同引擎分离 16
.1.6.5 简洁原则:设计要简洁,复杂度能低则低 17
1.6.6 吝啬原则: 除非确无它法,不要编写庞大的程序 18
1.6.7 透明性原则:设计要可见,以便审查和调试 18
1.6.8 健壮原则: 健壮源于透明与简洁 18
1.6.9 表示原则: 把知识叠入数据以求逻辑质朴而健壮 19
1.6.10 通俗原则:接口设计避免标新立异 20
1.6.11 缄默原则:如果一个程序没什么好说的,就保持沉默 20
1.6.12 补救原则: 出现异常时,马上退出并给出足量错误信息 21
1.6.13 经济原则: 宁花机器一分,不花程序员一秒 22
1.6.14 生成原则: 避免手工hack,尽量编写程序去生成程序 22
1.6.15 优化原则: 雕琢前先得有原型,跑之前先学会走 23
1.6.16 多样原则:决不相信所谓“不二法门”的断言 24
1.6.17 扩展原则: 设计着眼未来,未来总比预想快 24
1.7 unix哲学之一言以蔽之 25
1.8 应用unix哲学 26
1.9 态度也要紧 26
第2章 历史——双流记 29
2.1 unix的起源及历史,1969-1995 29
2.1.1 创世纪:1969-1971 30
2.1.2 出埃及记:1971-1980 32
2.1.3 tcp/ip 和unix内战:1980-1990 35
2.1.4 反击帝国:1991-1995 41
2.2 黑客的起源和历史:1961-1995 43
2.2.1 游戏在校园的林间:1961-1980 44
2.2.2 互联网大融合与自由软件运动:1981-1991 45
2.2.3 linux 和实用主义者的应对:1991-1998 48
2.3 开源运动:1998年及之后 49
2.4 unix的历史教训 51
第3章 对比: unix哲学同其他哲学的比较 53
3.1 操作系统的风格元素 53
3.1.1 什么是操作系统的统一性理念 54
3.1.2 多任务能力 54
3.1.3 协作进程 55
3.1.4 内部边界 57
3.1.5 文件属性和记录结构 57
3.1.6 二进制文件格式 58
3.1.7 首选用户界面风格 58
3.1.8 目标受众 59
3.1.9 开发的门坎 60
3.2 操作系统的比较 61
3.2.1 vms 61
3.2.2 macos 64
3.2.3 os/2 65
3.2.4 windows nt 68
3.2.5 beos 71
3.2.6 mvs 72
3.2.7 vm/cms 74
3.2.8 linux 76
3.3 种什么籽,得什么果 78
part ii 81
第4章 模块性:保持清晰,保持简洁 83
4.1 封装和最佳模块大小 85
4.2 紧凑性和正交性 87
4.2.1 紧凑性 87
4.2.2 正交性 89
4.2.3 spot原则 91
4.2.4 紧凑性和强单一中心 92
4.2.5 分离的价值 94
4.3 软件是多层的 95
4.3.1 自顶向下和自底向上 95
4.3.2 胶合层 97
4.3.3 实例分析:被视为薄胶合层的c语言 98
4.4 程序库 99
4.4.1 实例分析:gimp插件 100
4.5 unix和面向对象语言 101
4.6 模块式编码 103
第5章 文本化:好协议产生好实践 105
5.1 文本化的重要性 107
5.1.1 实例分析:unix口令文件格式 109
5.1.2 实例分析:.newsrc格式 110
5.1.3 实例分析:png图形文件格式 111
5.2 数据文件元格式 112
5.2.1 dsv 风格 113
5.2.2 rfc 822 格式 114
5.2.3 cookie-jar格式 115
5.2.4 record-jar格式 116
5.2.5 xml 117
5.2.6 windows ini 格式 119
5.2.7 unix文本文件格式的约定 120
5.2.8 文件压缩的利弊 122
5.3 应用协议设计 123
5.3.1 实例分析:smtp,一个简单的套接字协议 124
5.3.2 实例分析:pop3,邮局协议 124
5.3.3 实例分析:imap,互联网消息访问协议 126
5.4 应用协议元格式 127
5.4.1 经典的互联网应用元协议 127
5.4.2 作为通用应用协议的http 128
5.4.3 beep:块可扩展交换协议 130
5.4.4 xml-rpc,soap和jabber 131
第6章 透明性:来点儿光 133
6.1 研究实例 135
6.1.1 实例分析:audacity 135
6.1.2 实例分析:fetchmail的–v选项 136
6.1.3 实例分析:gcc 139
6.1.4 实例分析:kmail 140
6.1.5 实例分析:sng 142
6.1.6 实例分析:terminfo数据库 144
6.1.7 实例分析:freeciv数据文件 146
6.2 为透明性和可显性而设计 148
6.2.1 透明性之禅 149
6.2.2 为透明性和可显性而编码 150
6.2.3 透明性和避免过度保护 151
6.2.4 透明性和可编辑的表现形式 152
6.2.5 透明性、故障诊断和故障恢复 153
6.3 为可维护性而设计 154
第7章 多道程序设计: 分离进程为独立的功能 157
7.1 从性能调整中分离复杂度控制 159
7.2 unix ipc 方法的分类 160
7.2.1 把任务转给专门程序 160
7.2.2 管道、重定向和过滤器 161
7.2.3 包装器 166
7.2.4 安全性包装器和bernstein链 167
7.2.5 从进程 168
7.2.6 对等进程间通信 169
7.3 要避免的问题和方法 176
7.3.1 废弃的unix ipc方法 176
7.3.2 远程过程调用 178
7.3.3 线程——恐吓或威胁 180
7.4 在设计层次上的进程划分 181
第8章 微型语言:寻找歌唱的乐符 183
8.1 理解语言分类法 185
8.2 应用微型语言 187
8.2.1 案例分析:sng 187
8.2.2 案例分析:正则表达式 188
8.2.3 案例分析:glade 191
8.2.4 案例分析:m4 193
8.2.5 案例分析:xslt 194
8.2.6 案例分析:the documenter's workbench tools 195
8.2.7 案例分析:fetchmail的运行控制语法 199
8.2.8 案例分析:awk 200
8.2.9 案例分析:postscript 202
8.2.10 案例分析:bc和dc 203
8.2.11 案例分析:emacs lisp 205
8.2.12 案例分析:javascript 205
8.3 设计微型语言 206
8.3.1 选择正确的复杂度 207
8.3.2 扩展和嵌入语言 209
8.3.3 编写自定义语法 210
8.3.4 宏—慎用 210
8.3.5 语言还是应用协议 212
第9章 生成:提升规格说明的层次 215
9.1 数据驱动编程 216
9.1.1 实例分析:ascii 217
9.1.2 实例分析:统计学的垃圾邮件统计 218
9.1.3 实例分析:fetchmailconf中的元类改动 219
9.2 专用代码的生成 225
9.2.1 实例分析:生成ascii显示的代码 225
9.2.2 实例分析:为列表生成html代码 227
第10章 配置:迈出正确的第一步 231
10.1 什么应是可配置的 231
10.2 配置在哪里 233
10.3 运行控制文件 234
10.3.1 实例分析:.netrc文件 236
10.3.2 到其它操作系统的可移植性 238
10.4 环境变量 238
10.4.1 系统环境变量 238
10.4.2 用户环境变量 240
10.4.3 何时使用环境变量 240
10.4.4 到其它操作系统的可移植性 242
10.5 命令行选项 242
10.5.1 从–a到–z的命令行选项 243
10.5.2 到其它操作系统的可移植性 248
10.6 如何挑选方法 248
10.6.1 实例分析:fetchmail 249
10.6.2 实例分析:xfree86服务器 251
10.7 论打破规则 252
第11章 接口:unix环境下的用户接口设计模式 253
11.1 最小立异原则的应用 254
11.2 unix接口设计的历史 256
11.3 接口设计评估 257
11.4 cli和可视接口之间的权衡 259
11.4.1 实例分析:编写计算器程序的两种方式 262
11.5 透明度、表现力和可配置性 264
11.6 unix接口设计模式 266
11.6.1 过滤器模式 266
11.6.2 cantrip模式 268
11.6.3 源模式 268
11.6.4 接收器模式 269
11.6.5 编译器模式 269
11.6.6 ed模式 270
11.6.7 roguelike 模式 270
11.6.8 “引擎和接口分离”模式 273
11.6.9 cli服务器模式 278
11.6.10 基于语言的接口模式 279
11.7 应用unix接口设计模式 280
11.7.1
11.8 网页浏览器作为通用前端 281
11.9 沉默是金 284
第12章 优化 287
12.1 什么也别做,就站在那儿 287
12.2 先估量,后优化 288
12.3 非定域性之害 290
12.4 吞吐量和延迟 291
12.4.1 批操作 292
12.4.2 重叠操作 293
12.4.3 缓存操作结果 293
第13章 复杂度:尽可能简单,但别简过了头 295
13.1 谈谈复杂度 296
13.1.1 复杂度的三个来源 296
13.1.2 接口复杂度和实现复杂度的折中 298
13.1.3 必然的、可能的和偶然的复杂度 299
13.1.4 映射复杂度 300
13.1.5 当简洁性不能胜任 302
13.2 五个编辑器的故事 302
13.2.1 ed 304
13.2.2 vi 305
13.2.3 sam 306
13.2.4 emacs 307
13.2.5 wily 308
13.3 编辑器的适当规模 309
13.3.1 甄别复杂度问题 309
13.3.2 折衷无用 312
13.3.3 emacs是个反unix传统的论据吗 314
13.4 软件的适度规模 316
part iii 319
第14章 语言:c还是非c 321
14.1 unix下语言的丰饶 321
14.2 为什么不是c 323
14.3 解释型语言和混合策略 325
14.4 语言评估 325
14.4.1 c 326
14.4.2 c++ 327
14.4.3 shell 330
14.4.4 perl 332
14.4.5 tcl 334
14.4.6 python 336
14.4.7 java 339
14.4.8 emacs lisp 342
14.5 未来趋势 344
14.6 选择x工具包 346
第15章 工具:开发的战术 349
15.1 开发者友好的操作系统 349
15.2 编辑器选择 350
15.2.1 了解vi 351
15.2.2 了解emacs 351
15.2.3 非虔诚的选择:两者兼用 352
15.3 专用代码生成器 352
15.3.1 yacc和lex 353
15.3.2 实例分析:fetchmailrc的语法 356
15.3.3 实例分析:glade 356
15.4 make:自动化编译 357
15.4.1 make的基本理论 357
15.4.2 非c/c++开发中的make 359
15.4.3 通用生成目标 359
15.4.4 生成makefile 362
15.5 版本控制系统 364
15.5.1 为什么需要版本控制 364
15.5.2 手工版本控制 365
15.5.3 自动化的版本控制 366
15.5.4 unix的版本控制工具 367
15.6 运行期调试 369
15.7 性能分析 370
15.8 使用emacs整合工具 370
15.8.1 emacs和make 371
15.8.2 emacs和运行期调试 371
15.8.3 emacs和版本控制 371
15.8.4 emacs和profiling 372
15.8.5 像ide一样,但更强 373
第16章 重用:论不要重新发明轮子 375
16.1 猪小兵的故事 376
16.2 透明性是重用的关键 379
16.3 从重用到开源 380
16.4 生命中最美好的就是“开放” 381
16.5 何处找 384
16.6 使用开源软件的问题 385
16.7 许可证问题 386
16.7.1 开放源码的资格 386
16.7.2 标准开放源码许可证 388
16.7.3 何时需要律师 390
part iv 391
第17章 可移植性:软件可移植性与遵循标准 393
17.1 c语言的演化 394
17.1.1 早期的c语言 395
17.1.2 c 语言标准 396
17.2 unix 标准 398
17.2.1 标准和unix之战 398
17.2.2 庆功宴上的幽灵 401
17.2.3 开源世界的unix标准 402
17.3 ietf和rfc标准化过程 403
17.4 规格dna,代码rna 405
17.5 可移植性编程 408
17.5.1 可移植性和编程语言选择 409
17.5.2 避免系统依赖性 412
17.5.3 移植工具 413
17.6 国际化 413
17.7 可移植性、开放标准以及开放源码 414
第18章 文档:向网络世界阐释代码 417
18.1 文档概念 418
18.2 unix风格 420
18.2.1 大文档偏爱 420
18.2.2 文化风格 421
18.3 各种unix文档格式 422
18.3.1 troff和documenter's workbench tools 422
18.3.2 tex 424
18.3.3 texinfo 425
18.3.4 pod 425
18.3.5 html 426
18.3.6 docbook 426
18.4 当前的混乱和可能的出路 426
18.5 docbook 427
18.5.1 文档类型定义 427
18.5.2 其它dtd 428
18.5.3 docbook 工具链 429
18.5.4 移植工具 431
18.5.5 编辑工具 432
18.5.6 相关标准和实践 433
18.5.7 sgml 433
18.5.8 xml-docbook 参考书籍 433
18.6 编写unix文档的最佳实践 434
第19章 开放源码:在unix新社区中编程 437
19.1 unix和开放源码 438
19.2 与开源开发者协同工作的最佳实践 440
19.2.1 良好的修补实践 440
19.2.2 良好的项目、档案文件命名实践 444
19.2.3 良好的开发实践 447
19.2.4 良好的发行制作实践 450
19.2.5 良好的交流实践 454
19.3 许可证的逻辑:如何挑选 456
19.4 为什么应使用某个标准许可证 457
19.5 各种开源许可证 457
19.5.1 mit或者x consortium许可证 457
19.5.2 经典bsd许可证 457
19.5.3 artistic许可证 458
19.5.4 通用公共许可证 458
19.5.5 mozilla 公共许可证 459
第20章 未来:危机与机遇 461
20.1 unix传统中的必然和偶然 461
20.2 plan 9:未来之路 464
20.3 unix设计中的问题 466
20.3.1 unix文件就是一大袋字节 466
20.3.2 unix对gui的支持孱弱 467
20.3.3 文件删除不可撤销 468
20.3.4 unix假定文件系统是静态的 469
20.3.5 作业控制设计拙劣 469
20.3.6 unix api 没有使用异常 470
20.3.7 ioctl(2)和fcntl(2)是个尴尬 471
20.3.8 unix安全模型可能太过原始 471
20.3.9 unix名字种类太多 472
20.3.10 文件系统可能有害论 472
20.3.11 朝向全局互联网地址空间 472
20.4 unix的环境问题 473
20.5 unix文化中的问题 475
20.6 信任的理由 477
附录a 缩写词表 479
附录b 参考文献 483
附录c 贡献者 495
附录d 无根的根:无名师的unix心传 499
colophon 510
索引 511




下载地址:网盘下载

转载于:https://www.cnblogs.com/long12365/p/9732048.html

读--unix编程艺术

阅读数 207

unix编程艺术

阅读数 9

没有更多推荐了,返回首页