电子发烧友App

硬声App

0
  • 聊天消息
  • 系统消息
  • 评论与回复
登录后你可以
  • 下载海量资料
  • 学习在线课程
  • 观看技术视频
  • 写文章/发帖/加入社区
创作中心

完善资料让更多小伙伴认识你,还能领取20积分哦,立即完善>

3天内不再提示
电子发烧友网>电子资料下载>嵌入式开发>编写Linux实用程序的艺术

编写Linux实用程序的艺术

2017-11-01 | rar | 0.2 MB | 次下载 | 1积分

资料介绍

Linux 和其他类 UNIX 系统总是附带了大量的工具,它们执行从显而易见的到不可思议的广泛功能。类 UNIX 编程环境的成功很大程度上归功于工具的高品质和选择,以及这些工具之间相互衔接的简易性。
  作为开发人员,您可能会发现现有实用程序并不总是能够解决问题。虽然能够通过结合使用现有实用程序来容易地解决许多问题,然而解决其他问题却至少需要一些实际的编程工作。这些后面的任务通常是创建新实用程序的候选任务,结合现有实用程序来创建新实用程序可以通过做最少的工作来解决问题。本文考察优秀实用程序所具有的品质,以及设计这种实用程序所经历的过程。
  优秀的实用程序具有哪些品质?
  Kernighan & Pike 所著的 The UNIX Programming Environment 一书中包含了对此问题的精彩讨论。优秀的实用程序是把自己的工作做得尽可能好的实用程序。它必须与其他实用程序配合融洽;必须能够容易地与其他实用程序结合使用。无法与其他实用程序结合使用的程序不是实用程序,而是应用程序。
  实用程序应该允许您根据手边的材料廉价而容易地构建一次性的应用程序。许多人认为实用程序就像是工具箱中的工具。设计实用程序的目标不是为了让单个工具来做所有事情,而是为了拥有一组工具,其中每个工具都尽可能好地做一件事情。
  有些实用程序自身就是相当有用的,而其他实用程序则必须与一系列实用程序配合使用。前者的例子包括 sort 和 grep 。另一方面, xargs 除了与其他实用程序(最常见的是 find )配合使用外,很少单独使用。
  使用什么语言来编写实用程序?
  大多数 UNIX 系统实用程序都是用 C 语言来编写的。本文中的例子使用 Perl 和 sh。应该使用恰当的工具来做恰当的事情。如果您对某个实用程序使用得足够频繁,那么用编译型语言来编写它的成本也许能通过性能提升来获得回报。另一方面,对于程序的工作负荷很轻这种相当普遍的情况,使用脚本语言也许会提供更快的开发速度。
  如果无法肯定,您应该使用自己最了解的语言。至少当您在对某个实用程序进行原型化,或在弄清它是如何有用时,程序员效率将优先于性能调整。大多数 UNIX 系统实用程序都是用 C 编写的,这只是因为这些实用程序使用得足够频繁,以致考虑效率比考虑开发成本更加重要。Perl 和 sh(或 ksh)可能是用于快速原型化的很好语言。对于与其他程序配合实用的实用程序,使用 shell 来编写它们或许要比使用更传统的编程语言来编写它们要容易一些。另一方面,当您希望与原始的字节交互时,C 或许就是最好的选择。
  设计实用程序
  一个不错的经验法则就是当您第二次必须解决某个问题时,首先考虑实用程序的设计。不要对第一次编写的一次性作品感到遗憾;您可以将它看作是一个原型。第二次,请把您所需的功能与第一次所需的功能作比较。在第三次前后,您应该开始考虑花时间来编写一个通用实用程序。即使纯粹的重复性任务也可能会给实用程序的开发带来好处;例如,由于人们对尝试以通用的方式重命名文件感到失望,于是开发了许多通用文件重命名程序。
  下面是一些实用程序设计目标;每个目标将在下面单独的小节中介绍。
  做好一件事情。
  成为一个过滤器。
  通用化。
  健壮。
  新颖。
  做好一件事情
  做好一件事情;不要糟糕地做多件事情。关于做好一件事情的最佳例子或许是 sort 。除了 sort 外,没有 其他哪个实用程序具有排序功能。基本的思想很简单:如果一次仅解决一个问题,您就能花时间把它解决好。
  设想一下,如果大多数程序都具有排序功能,但是有些仅支持按词法排序,而其他一些仅支持按数字排序,另外一些甚至支持关键字选择而不是对整行排序,那将是一件多么令人沮丧的事情。起码,这也是恼人的。
  当您发现某个问题需要解决时,应尝试将问题分解为多个部分,不要重复那些其他实用程序中已经存在的部分。您对允许配合现有工具使用的工具关注得越多,您的实用程序就越有可能保持有用。
  也许您需要编写多个程序。完成专门任务的最佳途径通常是编写一两个实用程序,再用一些线索将它们联系起来,而不是编写单个程序来解决整件事情。使用 20 行的 shell 脚本来将新的实用程序与现有工具结合起来是很理想的。如果尝试一次解决整个问题,随之而来的第一个变更就可能要求您全盘重新考虑。
  我偶尔需要从数据库生成两列或三列的输出。编写一个程序在单个列中生成输出,然后结合使用一个对输出进行分列的程序,这样通常会更有效率。组合这两个实用程序的 shell 脚本本身是临时性的,单独的实用程序比这个脚本的使用寿命更长。
  有些实用程序服务于非常专一的需要。针对一个包含大量内容的目录,如果 ls 的输出非常快地滚出屏幕,这可能是因为其中有一个文件具有非常长的文件名,从而迫使 ls 仅对输出使用单个列。使用 more 来对输出分页会花一些时间。为什么不像下面这样就按长度对行排序,然后通过 tail 来管道输出结果呢?
  清单 1. 世间能找到的最小实用程序 sl
  #/usr/bin/perl -w
  print sort { length $a 《=》 length $b } 《》;
  清单 1 中的脚本确切地就做一件事情。它不接受任何选项,因为它不需要选项;它仅关心行的长度。归功于 Perl 便利的 《》 表达方式,这个小实用程序既适用于标准输入,也适用于命令行指定的文件。
  成为一个过滤器
  几乎所有实用程序都最适合想像为过滤器,尽管有一些非常有用的实用程序不符合这个模型。(例如,某个程序在执行计数时可能非常有用,尽管它作为过滤器工作得并不好。仅接受命令行参数作为输入并潜在地产生复杂输出的程序可能非常有用。)然而,大多数实用程序都应该作为过滤器来工作。根据惯例,过滤器对文本的行起作用。大多数过滤器都应该支持多个输入文件。
  记住实用程序需要在命令行和脚本中运行。有时,理想的行为会稍有不同。例如,大多数版本的 ls 都会在向终端写出时自动将输入排序到多个列中。 grep 的默认行为是在指定多个文件的情况下打印从其中找到匹配项的那个文件名称。这样的差别应该与用户希望的实用程序工作方式有关,而不是与其他事项有关。例如,旧版本的 GNU bc 在启动时显示强迫性的版权标记。请不要那样做。让您的实用程序仅做它应该做的事情。
  实用程序喜欢生活在管道中。管道允许实用程序专注于自己的工作,而不是去关注旁枝末节。为了生活在管道中,实用程序需要从标准输入读取数据,然后向标准输出写出数据。如果您希望处理记录,那么您最好能够使每一行成为一个“记录”。诸如 sort 和 join 之类的现有程序已经在那样考虑了。它们将会因为您这样做而感谢您。
  我偶尔使用这样一个实用程序,它针对一个文件树反复调用其他程序。这充分利用了标准的 UNIX 实用程序过滤器模型,但是该模型仅适用于读取输入然后写出输出的实用程序;不能将它用于就地操作或接受输入输出文件名的实用程序。
  可以使用标准输入来运行的大多数程序也完全可以针对单个文件或一组文件运行。注意,可以证明这样违背了反对重复工作的规则;显而易见,这可以通过将 cat 的输出馈送给该系列中的下一个程序来解决。然而这在实践中似乎是合理的。
  有些程序可能合法地读取一种格式的记录,但是却产生完全不同的输出。这样的一个例子就是将输入材料划分为列的实用程序。这样一个实用程序可能将输入中的行视为记录,但是却在输出中的每行上产生多个记录。
  并非每个实用程序都完全符合这个模型。例如, xargs 不是接受记录而是接受文件名作为输入,并且所有的实际处理都是由其他程序完成的。
  通用化
  尝试将任务看作与您实际执行的任务类似;如果您能找出这些任务的通用描述,那么最好尝试编写一个符合该描述的实用程序。例如,如果您发现自己一天在根据词法对文本排序,而另一天在根据数字对文本排序,那么考虑编写一个通用排序实用程序也许是有意义的。
  对功能进行通用化有时会导致您发现:某个看起来似乎像单个实用程序的程序,实际上却是配合起来使用的两个实用程序。这很好。编写两个设计良好的实用程序可能要比编写一个丑陋的或复杂的实用程序更容易。
  做好一件事情并不意味着 仅仅做一件事情。它意味着处理一致但有用的问题空间。许多人都使用 grep 。然而,它的大量效用在于执行相关任务的能力。 grep 的各种选项完成许多小实用程序的工作,如果这些工作都由单独的小实用程序来完成,最终会造成大量共享的、重复的代码。
  这条规则,以及做好一件事情的规则,都是一个根本原理的必然结果:无论何时都要尽可能避免代码重复。如果您编写半打程序,其中每个都对行排序,您最终可能必须六次修复六个类似的 bug,而不是去使用一个得到更好维护的 sort 程序。
  这是编写实用程序的一部分,即把大多数工作添加到完成该实用程序的过程中。您也许没有时间在最初就完全通用化一个实用程序,但是当您一直使用该实用程序就会获得相应的回报。
  有时,向某个程序添加相关功能是很有用的,即使这个功能并不是用来完成完全相同的任务。例如,当运行在终端设备上时,对原始二进制数据进行完美打印的程序可能更为有用,因为它使终端进入原始模式。这样使得测试涉及键盘映射、新键盘等的问题变得容易多了。不确定为什么当您按 delete 键时却得到代字号(~)吗? 这是弄清实际发送了什么内容的容易途径。这并不是完全相同的任务,但它足够类似,因而可能成为一个附加特性。
  清单 2 中的 errno 实用程序就是通用化的很好例子,因为它同时支持数字和符号名称。
  健壮
  实用程序的稳定性是很重要的。容易崩溃或无法处理真实数据的实用程序不是有用的实用程序。实用程序应该能够处理任意长度的行、巨型文件,等等。实用程序无法处理超过其内存容量的数据集或许是可以容忍的,但是有些实用程序不是这样;例如, sort 通过使用临时文件,一般能够对比其内存容量大得多的数据集排序。
  应该尽量确保弄清楚您的实用程序可能要操作哪些数据。不要简单地忽略无法处理的数据的可能性。应该检查这种情况并诊断您的实用程序。错误消息越明确,您对用户就越有帮助。尽量给用户提供足够的信息,以便让他们知道发生了什么情况以及如何解决。当处理数据文件时,尽量准确识别出不良的数据。当尝试解析数字时,不要简单地放弃;应该告诉用户您得到了什么数据,而且如果可能的话,还应该告诉用户该数据位于输入流中的哪一行上。
  作为一个很好的例子,请考虑 dc 的两种实现之间的区别。如果您运行 dc /home ,其中一种实现会显示“Cannot use directory as input!”而另一种实现只是无声地返回,没有错误消息,也没有不寻常的退出代码。当您错误地键入一个 cd 命令时,您更希望当前路径中有哪一种实现呢?类似地,如果您提供某个目录中的数据流(或许是执行 dc 《 /home ),前者会给出详细的错误消息。另一方面,当它在获得无效数据的早期就选择放弃可能是理想的。
  安全漏洞经常植根于在意料之外的数据面前表现得不够健壮的程序中。务必记住,优秀的实用程序能够设法在 shell 脚本中作为根(root)用户身份运行。诸如 find 这样的程序中的缓冲区溢出可能会给大量的系统带来风险。
  程序对意料之外的数据处理得越好,它就更可能适应变化的环境。通常,设法使程序更健壮会导致您更好地理解该程序的作用,从而更好地使之通用化。
  新颖
  要编写的最糟糕的实用程序种类之一就是您已经有了的实用程序。我编写过一个名为 count 的美妙的实用程序。它允许我执行几乎任何计数任务。它是一个出色的实用程序,但是已经有一个名为 jot 的标准 BSD 实用程序做同样的事情。同样地,我的一个用于将数据转换为列的灵活的程序重复了一个现有实用程序 rs 的功能,这个实用程序同样可以在 BSD 系统上找到,只不过 rs 更灵活,设计得更好。请参阅下面的 参考资料 以了解关于 jot 和 rs 的更多信息。
下载该资料的人也在下载 下载该资料的人还在阅读
更多 >

评论

查看更多

下载排行

本周

  1. 1TC358743XBG评估板参考手册
  2. 1.36 MB  |  330次下载  |  免费
  3. 2开关电源基础知识
  4. 5.73 MB  |  6次下载  |  免费
  5. 3100W短波放大电路图
  6. 0.05 MB  |  4次下载  |  3 积分
  7. 4嵌入式linux-聊天程序设计
  8. 0.60 MB  |  3次下载  |  免费
  9. 5基于FPGA的光纤通信系统的设计与实现
  10. 0.61 MB  |  2次下载  |  免费
  11. 6基于FPGA的C8051F单片机开发板设计
  12. 0.70 MB  |  2次下载  |  免费
  13. 751单片机窗帘控制器仿真程序
  14. 1.93 MB  |  2次下载  |  免费
  15. 8基于51单片机的RGB调色灯程序仿真
  16. 0.86 MB  |  2次下载  |  免费

本月

  1. 1OrCAD10.5下载OrCAD10.5中文版软件
  2. 0.00 MB  |  234315次下载  |  免费
  3. 2555集成电路应用800例(新编版)
  4. 0.00 MB  |  33564次下载  |  免费
  5. 3接口电路图大全
  6. 未知  |  30323次下载  |  免费
  7. 4开关电源设计实例指南
  8. 未知  |  21548次下载  |  免费
  9. 5电气工程师手册免费下载(新编第二版pdf电子书)
  10. 0.00 MB  |  15349次下载  |  免费
  11. 6数字电路基础pdf(下载)
  12. 未知  |  13750次下载  |  免费
  13. 7电子制作实例集锦 下载
  14. 未知  |  8113次下载  |  免费
  15. 8《LED驱动电路设计》 温德尔著
  16. 0.00 MB  |  6653次下载  |  免费

总榜

  1. 1matlab软件下载入口
  2. 未知  |  935054次下载  |  免费
  3. 2protel99se软件下载(可英文版转中文版)
  4. 78.1 MB  |  537796次下载  |  免费
  5. 3MATLAB 7.1 下载 (含软件介绍)
  6. 未知  |  420026次下载  |  免费
  7. 4OrCAD10.5下载OrCAD10.5中文版软件
  8. 0.00 MB  |  234315次下载  |  免费
  9. 5Altium DXP2002下载入口
  10. 未知  |  233046次下载  |  免费
  11. 6电路仿真软件multisim 10.0免费下载
  12. 340992  |  191185次下载  |  免费
  13. 7十天学会AVR单片机与C语言视频教程 下载
  14. 158M  |  183278次下载  |  免费
  15. 8proe5.0野火版下载(中文版免费下载)
  16. 未知  |  138040次下载  |  免费