本书前言的译文
这篇书评可能有关键情节透露
前言
主题
本书将描述Linux编程接口:由UNIX操作系统的开源实现——LINUX所提供的系统调用、库函数以及其它底层接口。运行于LINUX之上的每一程序都会直接或间接地使用这些接口。这些接口允许应用程序去执行诸多任务:文件I/O、创建/删除文件和目录、创建新进程、执行程序、设置计时器、在同一计算机上发起进程或线程间通信,以及为联网计算机间的进程建立通信等等。有时,人们也将这一系列的底层接口称为系统编程接口。
尽管本书着眼于LINUX,但对于标准和可移植性问题也倍加关注。对于LINUX所特有的技术细节,以及已由POSIX和SUS标准化的UNIX普遍特性,本书会在论述中清晰地加以区分。因此,本书亦提供了对UNIX/POSIX编程接口的全面描述。对于那些在其它UNIX系统环境中编程,或者编写跨平台可移植应用程序的程序员来说,本书同样具有实用价值。
本书的读者
本书主要针对以下读者:
为LINUX系统、其他UNIX系统,或兼容于POSIX的操作系统编写应用程序的程序员和软件设计人员。
在LINUX和其它UNIX实现之间,以及LINUX和其它操作系统之间进行应用程序移植的程序员。
教/学LINUX和UNIX系统编程的高校师生。
意欲深入理解LINUX/UNIX编程接口、以及系统软件各模块实现细节的系统管理人员和高级用户(power users)。
笔者假定读者之前有过些许编程经验,但不必是在系统编程领域。此外,笔者还假定读者具备阅读C语言源码的能力,并了解如何使用shell和UNIX或LINUX的常用命令。对于不熟悉UNIX和LINUX的读者来说,阅读第二章中面向程序员对UNIX和LINUX系统基本概念所做的回顾会有所帮助。
提示:[Kernighan & Ritchie, 1988]是最具权威性的C语言参考书籍。[Harbison& Steele, 2002]一书对C语言的介绍则更为详细,并涵盖了由C99标准所带来的变化。[van der Linden, 1994]也是一本不错的C语言书籍,寓教于乐。[Peek et al., 2001]则对UNIX的使用做了简洁而完整的介绍。
贯穿本书,会以这种缩进小字体的文字形式用于旁注,其内容包括:基本原理、实现细节、背景信息、史上轶闻以及与正文相关的其它辅助主题。
LINUX和UNIX
其它UNIX实现的大多数特性同样见诸于Linux,反之亦然。有鉴于此,本书本可只关注于标准UNIX(即POSIX)的系统编程。编写可移植的应用程序固然是值得追求的目标,但描述LINUX对标准UNIX编程接口的扩展也同样重要。LINUX的广受欢迎只是原因之一,而有时出于性能方面的考虑,或是需要访问标准UNIX编程接口所不支持的功能时,使用非标准扩展(正因如此,所有UNIX实现都提供有非标准扩展)就显得至为重要,此为原因之二。
综上所述,在构思本书时,笔者不但力图使其对在各种UNIX实现中编程的程序员有所帮助,还全面介绍了LINUX专有的编程特性。这包括:
. epoll ,获取文件I/O事件通知的一种机制。
. inotify ,监控文件和目录变化的一种机制。
.capabilities, 为进程赋予超级用户的部分权限的一种机制。
.扩展属性
. i-node标记
. clone()系统调用
. /proc文件系统
.在文件I/O、信号、计时器、线程、共享库、进程间通信以及套接字方面LINUX所专有的实现细节。
本书的用途和组织结构
本书主要具备以下两种用途:
.作为Linux/UNIX编程接口的入门教程。读者可循序阅读本书。后续各章内容均构建于之前诸章素材的基础之上,伴之以尽可能简短的前向引用。
.作为Linux/UNIX编程接口的参考大全。读者可以根据书后的详细索引和正文中频繁出现的交叉引用,随机选择阅读主题。
本书各章可分为以下几个部分:
1、背景知识及概念:UNIX、C语言以及LINUX的历史回顾,以及对UNIX标准的概述(第一章);以程序员为对象,对LINUX和UNIX的概念进行介绍(第二章);LINUX和UNIX系统编程的基本概念(第三章)。
2、系统编程接口的基本特性:文件I/O(四、五两章);进程(第六章);内存分配(第七章);用户和组(第八章);进程凭证(process credential)(第九章);时间(第十章);系统限制和选项(第十一章);以及获取系统和进程信息(第十二章)。
3、系统编程接口的高级特性:文件I/O缓冲(第十三章);文件系统(第十四章);文件属性(第十五章);扩展属性(第十六章);访问控制列表(第十七章);目录和链接(第十八章);监控文件事件(第十九章);信号(signals)(二十至二十二章);以及计时器(第二十三章)。
4、进程、程序及线程:进程的创建、终止,监控子进程,执行程序(二十四至二十八章);以及POSIX线程(二十九至三十三章)。
5、进程及程序的高级主题:进程组、会话以及任务控制(第三十四章);进程优先级和进程调度(第三十五章);进程资源(第三十六章);守护进程(第三十七章);编写安全的特权程序(第三十八章);能力(capability)(第三十九章);登陆记账(第四十章);以及共享库(四十一和四十二两章)。
6、进程间通信(IPC):IPC概览(第四十三章);管道和FIFO(第四十四章);系统V IPC消息队列、信号(semaphore)及共享内存(四十五至四十八章);内存映射(第四十九章);虚拟内存操作(第五十章);POSIX消息队列、信号及共享内存(五十一至五十四章);以及文件锁定(第五十五章)。
7、套接字和网络编程:使用套接字的IPC和网络编程(五十六至六十一章)。
8、高级I/O主题:终端(第六十二章);其它I/O模型(第六十三章);以及伪终端(第六十四章)。
程序示例
本书会以简短而完整的程序示例来描述大部分编程接口,以期读者通过命令行方便地体验这些程序,从而了解各种不同系统调用和库函数的运作方式。因此,本书包含了大量代码示例——约15000行C语言代码和shell会话记录。
虽然阅读并执行上述示例代码是学习LINUX编程接口的一个不错的起点,但巩固本书所述概念最为有效的方式还是动手编写代码——无论是修改示例程序以验证自己的编程思路,还是编写全新的程序。
书中所有源代码均可从本书网站上下载。网站所发布的源码中还包含了不少未见诸于本书的额外程序。这些程序的用途和详细信息在源码注释中均有描述。源码中还提供了Makefile,用来构建相应的程序,附带的README文件则提供了相应程序的具体细节。
在GNU Affero通用公共许可证(Affero GPL)版本3条款的约束之下,可自由地再行发布和修改本书源码,源代码中也提供了一份GNU Affero GPL版本3的文件副本。
习题
本书各章大都会在结尾处附有一组习题,其中一部分会利用书中的程序示例进行各种试验。另一些习题中的问题则与本章所讨论的概念相关,而其它习题则是引导读者亲自动手编程,意在巩固读者对所学内容的理解。附录F会有选择地给出部分习题的答案。
标准和可移植性
本书自始至终都对可移植性问题予以了特殊关注。对相关标准的引用在书中会频繁出现,尤其是POSIX.1-2001和SUSv3的联合标准(译者注:其实是一套标准的两种称谓,下同)。此外,本书还包括了该标准最新版本(POSIX.1-2008与SUSv4联合标准)的变动细节。(由于SUSv3(较之于之前的版本)做了大范围的修订,并且在写作本书之际,SUSv3依然是影响最为广泛的UNIX标准,故而本书对标准的讨论一般都以SUSv3为框架,并会注明其与SUSv4之间的差别。然而,对读者来说,除非另有说明,与SUSv3规范有关的论述同样适用于SUSv4。)
对于那些尚未标准化的特性,本书会列出与其它UNIX实现间的差异范围。此外,本书也会强调那些独具LINUX实现特色的主要特性,以及LINUX和其它UNIX实现之间在系统调用和库函数方面的细微差别。任何特性,凡未注明为LINUX所专有,读者通常可将其视同为大部分或所有UNIX实现的标准特性。
书中的编程示例(除了注明为LINUX所专有的特性)大多已在Solaris、FreeBSD、 Mac OS X、Tru64 UNIX以及HP-UX中的所有或部分系统上进行了测试。为了改进针对其中某些系统的可移植性,本书的WEB站点还为特定编程示例提供了其它版本,额外的代码并未在本书中出现。
LINUX内核和C语言库版本
本书主要着眼于Linux 2.6.x,撰写本书之际,这一内核版本的使用也最为广泛。本书同样涵盖了LINUX2.4内核的详细信息,也会适时指明LINUX2.4和2.6内核间特性的差异。凡是见诸于LINUX2.6.x系列中的新特性,笔者均会标出其(首度)出现的确切内核版本号(例如,2.6.34)。
至于C语言库,本书会重点关注GNU C库(glibc)版本2。本书也会适时指出glibc 2.x版本之间所存在的差异。
本书付梓之际,LINUX内核版本2.6.35刚刚问世,不久又发布了glibc版本2.12。本书目前的论述涵盖了以上两种软件的这两个版本。本书出版之后,LINUX和glibc接口所发生的变化会在本书的WEB站点上公布。
在其它语言中调用编程接口
虽然本书的程序示例都以C语言编写而成,但读者也能使用其它编程语言来调用本书所描述的编程接口,这些语言既包括编译语言,例如:C++、Pascal、Modula、Ada、FORTRAN和D语言;也包括脚本语言,例如:Perl、Python和Ruby(如要使用java,则需另辟蹊径,可参阅[Rochkind, 2004])。需要运用不同的技术以获取必要的常量定义和函数申明(C++除外),而按C语言链接惯例所约定的方式来传递函数参数可能也需要额外的工作投入。虽然实现起来有差异,但基本原理却都相同,即便读者在使用其他语言进行编程,本书所含信息对他们也同样适用。
关于作者
本人于1987年开始使用UNIX和C语言。当时,笔者连续几个礼拜都泡在一台HP Bobcat工作站旁,陪伴我的只有Marc Rochkind所著《Advanced UNIX Programming》一书的第一版,和一本最终被翻得卷了边的C shell手册的印刷本。投入时间阅读文档(如果有的话),并编写一些小型的(规模可逐渐变大)测试程序进行试验,直至自己对软件的理解感到信心满满——这是笔者当时所采用的编程学习方法,并一直沿用至今——笔者也向任何试水新型软件技术的人们推荐这一做法。依笔者拙见,从长远来看,这种自学方法能够大大节约时间。本书所载的许多编程示例正是在这一学习方法的激励之下设计而成。
笔者的主要身份是软件工程师和设计师。然而,笔者同样好为人师,并已在学术或商业领域有过数年的教学经验。笔者还开设过多门为期一周的UNIX系统编程课程,这一经验对本书的写作也颇有影响。
笔者使用LINUX的时间大约只有与UNIX打交道的时间一半长,在这段时间里,笔者的兴趣也逐渐集中在了内核和用户空间的“分水岭”——LINUX编程接口上。这一兴趣也将笔者置身于一系列相互关联的活动中。笔者会时不时地对POSIX/SUS标准提出自己的意见并提供BUG报告;对新加入LINUX内核中的用户空间接口进行测试和设计评审(还能帮助发现并修复那些接口中的诸多代码和设计缺陷);笔者还经常在关于编程接口及其文档的主题会议上发言,并受邀多次出席LINUX内核开发者年度峰会。将上述所有事迹串接在一起的主线是笔者对LINUX领域最醒目的贡献:笔者为LINUX man-pages项目(http://www.kernel.org/doc/man-pages/)所做的工作。
LINUX手册页中的2、3、4、5以及第7部分都属于man-pages项目。这几部分也是手册页中描述编程接口的内容,这些编程接口由LINUX内核及GNU C语言库所提供——本书所要介绍的正是这方面的内容。笔者参与man-pages项目已逾十载。自2004年起,笔者成为了该项目的主要维护人,所承担的任务大致包括:撰写文档、阅读内核和C语言库源码,以及通过编程来验证文档的细节(通过为接口撰写文档来发现相关接口中的BUG,效果颇为不凡)。此外,笔者对man-pages项目的贡献也最大——在约900页的手册页中,笔者独自编写了其中的140页,并与他人合著了另外的125页。因此,在购买本书之前,读者想必已经阅读过本人的工作成果了。笔者希望这些成果能对读者有所帮助——希望本书更是如此。
致谢
没有一干人等的支持,本书的质量绝不会如此之高。我要向他们致以最诚挚的谢意。
来自世界各地的一大票技术审稿人都参与了本书初稿的阅件,找出错误,指出含糊不清的解释,对措辞、插图以及习题提出建议,测试程序,发现不为笔者所知的LINUX和其它UNIX实现间的行为差异,并不时为笔者打气助威。在本书中,笔者将许多审稿人无私奉献的真知灼见一并收纳,实则笔者的知识并非如此渊博。当然,书中的任何错误都是笔者一人之过。
无论以下技术审稿人(按姓氏字母排序)对本书手稿的审校巨细与否,篇幅多少,笔者都要向他们致以由衷的谢意:
. Christophe Blaesss是一名软件咨询工程师和培训专家,专长是LINUX在工业(实时和嵌入)方面的应用。Christophe是《Programmation système en C sous Linux》一书的作者,这本法文杰作涵盖了与本书相同的多项主题。他不吝审阅了本书的众多章节。
.David Butenhof(HP公司)是原POSIX线程工作组和SUS线程扩展工作组的成员之一,也是《Programming with POSIX Threads》一书的作者。他曾为开放软件基金会编写了最初的DCE线程参考实现,并曾担任OpenVMS and Digital UNIX线程实现的首席架构师。David审校了本书与线程相关的章节,提出了诸多改进意见,还耐心地纠正了几处笔者对POSIX线程API的理解错误。
. Geoff Clare 目前在为The Open Group开发UNIX一致性测试包,从事UNIX 标准化工作已逾20年,是 Austin Group 的6位关键参与者之一, 该组的宗旨是开发出构成POSIX.1和Single UNIX Specification基础卷的共同标准。Geoff仔细审校了手稿中与UNIX编程接口相关的内容,耐心细致地提出了众多修正和改进意见,发现了诸多潜藏于手稿中的错误,在突出标准对可移植编程的重要性方面助益颇多。
. Loïc Domaigné(当时供职于德国空中管制中心(German Air Traffic Control))是一名系统软件工程师,主要从事分布式、多并发的容错型嵌入式系统的设计和开发,此类系统对实时性有着严苛的要求。他针对SUSv3中与线程规范有关的内容发表过评论和建议,在多个网上技术论坛中古道热肠、诲人不倦,无私的分享自己的编程心得。Loïc细致地审校了本书与线程有关的章节,以及多处其它内容。除了编写若干精巧的程序来验证LINUX线程实现的细节以外,他还倾注了巨大的热情并鼓励笔者,提出了许多建议以改进本书整体的表现形式。
. Gert Döring mgetty和sendfax程序的开发者,这对“双子星座”也是LINUX/UNIX系统上使用最为广泛的开源传真软件包。最近,他主要忙于搭建并维护基于IPv4和IPv6的大型网络,其肩负的主要任务是:与全欧洲的同事一起定义有效的网络策略,以确保Internet基础设施顺畅运行。Gert审校了本书与终端、登陆记账、进程组、会话以及任务控制有关的章节,并提供了大量有用的反馈信息。
. Wolfram Gloger 是一名IT顾问,过去十五年来,他参与过许多自由和开源软件项目(Free and Open Source Software (FOSS))。除此之外,Wolfram还是GNU C语言库中malloc软件包的实现者。目前,他主要从事于WEB服务的开发,尤其专注于网上教学,当然,在内核和系统库方面,他仍会偶露峥嵘。Wolfram审校了本书多个章节,尤其侧重于内存方面的内容。
. Fernando Gont 是阿根廷国家科技大学(Universidad Tecnológica Nacional, Argentina)电子信息中心(Centro de Estudios de Informática (CEDI))成员。Internet工程技术(Internet engineering)是其兴趣所在,在Internet工程任务组(IETF)也能见到其活跃的身影,他还是多个RFC文档的作者。此外,Fernando还为英国CPNI(国家基础设施保护机构)中心效力,以提供对通信协议安全方面的评估,而首个完整的TCP和IP协议安全评估报告也正是由他提出。Fernando仔细审校了本书涉及网络编程的相关章节,不厌其烦地向作者解释了TCP/IP协议的诸多细节,并对相关内容提出了不少改进意见。
. Andreas Grünbacher(SUSE实验室)是为内核高手,并且是LINUX扩展属性和POSIX访问控制列表实现的作者。Andreas除了仔细审校了本书多章内容以外,还对笔者勉励有加,有时,只言片语便极有可能改变了整部书的结构。
. Christoph Hellwig LINUX存储和文件系统咨询师,也是内核方面公认的行家,参与过LINUX内核中多个部分的开发工作。在编写及审查LINUX内核补丁代码的工作之余,Christoph抽空审校了本书若干章节,并提出了诸多有益的改进和修正意见。
. Andreas Jaeger 曾领导过LINUX向x86-64架构的移植开发工作。身为GNU C语言库的开发者,他不但将该库移植到了x86-64平台,而且还促成该库符合多个领域的标准,尤其在数学库方面。他当前效力于Novell公司,是openSUSE的程序经理。Andreas审校的章节之多,超乎笔者预期。在本书的写作过程中,他除了提出诸多改进意见之外,亦给予笔者热情的鼓励。
. Rick Jones 绰号“Mr. Netperf”(HP公司联网系统的性能偏执狂),对本书的网络编程相关章节提出了宝贵意见。
. Andi Kleen (当时效力于SUSE实验室)长期以来,一直是内核方面公认的行家里手,对LINUX内核诸多不同领域贡献颇多,包括:网络、错误处理以及底层架构代码等方面。Andi对网络编程相关内容做了全面审校,拓展了笔者在LINUX TCP/IP的实现方面的眼界,此外,他还提供了许多建议,用来改善本书主题的展现形式。
. Martin Landers(google)在我有幸和他成为同事时,他还是一名学生。其后,他在短期内便集诸多技能于一身,且形象百变——软件架构师、IT培训师及职业黑客。劳Martin大驾审校本书,是笔者的荣幸。他对本书的评论和更正往往一针见血,对多章内容质量的改进功莫大焉。
.Jamie Lokier 是公认的内核高手,投身于LINUX开发已达15年之久。如今,他自封为“专家,长于解决潜伏于LINUX系统中的疑难杂症”。Jamie极其全面地审校了本书涉及内存映射、POSIX共享内存以及虚拟内存操作等方面的章节。他的审校工作不但纠正了笔者对相关主题细节方面的许多误解,相应各章的结构也得以大为改观。
. Barry Margolin 在其25年职业生涯中,从事过系统程序员、系统管理员以及技术支持工程师。当前,他作为一名系统性能工程师,供职于Akamai技术公司。在各种讨论UNIX和Internet技术主题的网上论坛中,他频频现身、威名素著。他还是多本相关技术主题书籍的技术审稿人。Barry审校了本书若干章节,并提出了诸多改进意见。
. Paul Pluzhnikov(google)之前曾是Insure++内存调试工具的技术带头人和主要开发者。有时,他也会以GDB黑客的身份现身,在网上论坛里积极地回复有关调试、内存分配、共享库以及运行时环境方面的问题。Paul审校了本书多章内容,提出了许多宝贵意见。
. John Reiser (会同Tom London),实现了UNIX向32位架构移植的早期版本之一: VAX-11/780。他还是mmap()系统调用的编写者。John审校了本书多章内容(自然也包括mmap()所在的章节)。他所提供的大量历史洞见、及其对技术透彻地阐释为本书相关章节增色不少。
. Anthony Robins(新西兰Otago大学计算机科学副教授)笔者30年的密友,本书某些章节的第一个读者,也是最早提出宝贵意见的技术审校者,在本书的写作过程中,一直给予笔者以激励。
. Michael Schröder (Novell) GNU screen程序的主要开发者之一,这项编程工作已令其在终端驱动程序的实现方面达到了“巨细靡遗,了如指掌”的境界。Michael除了审校本书与终端和伪终端有关的章节以外,还针对进程组、会话以及任务控制等章节提出了极为有益的反馈意见。
. Manfred Spraul 曾从事过LINUX内核中(包括但不限于)IPC的开发工作,不吝审校了本书与IPC相关的若干章节,并提出了许多改进意见。
. Tom Swigg 笔者在DEC从事培训工作时曾与他共事,作为本书最早的技术审校者之一,他对许多章节都提出了重要的反馈意见。Tom从事软件工程师和IT培训师的工作已逾25年,目前就职于伦敦南岸大学(London South Bank University),在Vmware环境下从事LINUX编程和技术支持工作。
. Jens Thoms Törring 继承了物理学家改学编程的优良传统,大批开源的设备驱动程序和其它软件都出自他手。Jens审校的章节之多,在技术方面跨度之大,着实令人瞠目,他对各章内容的改进都提出了独特而又弥足珍贵的见解。
还有许多其他技术审稿人也审校了本书的不同内容,并提出了诸多宝贵意见。在此,笔者向以下一干技术审稿人表示感谢(以姓氏字母顺序排列):George Anzinger (MontaVista Software), Stefan Becher, Krzysztof Benedyczak, Daniel Brahneborg, Andries Brouwer, Annabel Church, Dragan Cvetkovic, Floyd L. Davidson, Stuart Davidson (Hewlett-Packard Consulting), Kasper Dupont, Peter Fellinger (jambit GmbH), Mel Gorman (IBM), Niels Göllesch, Claus Gratzl, Serge Hallyn (IBM),Markus Hartinger (jambit GmbH), Richard Henderson (Red Hat), Andrew Josey (The Open Group), Dan Kegel (Google), Davide Libenzi, Robert Love (Google), H.J. Lu (Intel Corporation), Paul Marshall, Chris Mason, Michael Matz (SUSE),Trond Myklebust, James Peach, Mark Phillips (Automated Test Systems), Nick Piggin(Novell SUSE实验室), Kay Johannes Potthoff, Florian Rampp, Stephen Rothwell (IBM Linux技术中心), Markus Schwaiger, Stephen Tweedie (Red Hat), Britta Vargas, Chris Wright, Michal Wronski以及 Umberto Zamuner。
除了技术审稿人之外,笔者还得到了各界人士及组织在其它方面的帮助。
我要感谢以下一干人等为我解答技术难题,他们是:Jan Kara、Dave Kleikamp和Jon Snader。我要感谢Claus Gratzl和Paul Marshall在系统管理方面对我的帮助。
我要感谢LINUX基金会(LF)。2008年间,LF资助我作为一名全职研究人员参与man-pages项目、并从事LINUX编程接口的测试和设计评审工作。虽然LF全职研究员的身份不能为本书的写作提供直接的资金支持,但却使笔者得以养家糊口,这一助力初衷在于令我全身心投入对LINUX编程接口的测试以及对文档的编纂工作,却也惠及笔者的 “私活”。抛开公事不谈,我要感谢Jim Zemlin——我在LF的“接口”人。还要感谢LF技术咨询委员会的一干专家,感谢他们聘我为全职研究员。
感谢Alejandro Forero Cuervo对本书书名的建议!
25年多前,在我为第一个学位拼搏之时,Robert Biddle激起了我对UNIX、C,以及Ratfor的兴趣,谢谢你,老兄。虽然以下一干人等对本书并无直接干系,但当我在新西兰坎特伯雷大学攻读第二学位时,他们就鼓励我在写作道路上坚持走下去,在此,我要向他们表示感谢,他们是:Michael Howard, Jonathan Mane-Wheoki, Ken Strongman, Garth Fletcher, Jim Pollard,以及Brian Haig。
由Richard Stevens所著的几部关于UNIX编程和TCP/IP方面的杰作,数年来一直被我辈程序员奉为技术的神奇源泉,只可惜先贤已逝。凡是读过上述书籍的读者势必会注意到,本书与Richard Stevens的那几本巨著看起来有些相似。这并非偶然。在构思本书时,笔者曾从较为宏观的角度就书籍设计反复斟酌,可最终发现Richard Stevens所采用的方法才是正解,正因如此,本书采用了与其相同的展示方式。
感谢下列人士和组织为我提供UNIX系统,使我得以运行测试程序,并验证其它UNIX实现的细节:感谢Anthony Robins和Cathy Chandra在新西兰Otago大学所提供的多种UNIX测试系统;感谢Martin Landers, Ralf Ebner和 Klaus Tilk在德国慕尼黑技术大学(Technische Universität)所提供的多种UNIX测试系统;感谢HP公司在Internet上免费开放他们的testdrive系统;感谢Paul de Weerd使我得以访问OpenBSD系统。
要衷心感谢两家慕尼黑公司及其老板,这两家公司除了为我提供了工作机会(还是弹性工作制)和热情的同事,还格外开恩,允许我在写作本书之时使用他们的办公室。感谢exolution有限公司的Thomas Kahabka和Thomas Gmelch,特别要感谢jambit 有限公司的Peter Fellinger和Markus Hartinger。
感谢下列人士对我提供的各种帮助,他们是:Dan Randow, Karen Korrel, Claudio Scalmazzi, Michael Schüpbach, and Liz Wright。感谢Rob Suisted和Lynley Cook为封面和封底所提供的照片。
感谢下列人士以不同方式给笔者以鼓励和支持,他们是:Deborah Church, Doris Church和Annie Currie。
感谢No Starch出版社大队人马为这一庞大的创作项目所提供的各种帮助。Bill Pollock从项目之初就一直秉持直言不讳的风格,始终对本书的完成充满信心,并耐心地关注着项目的进展,我要对他表示感谢。感谢本书最初的责编Megan Dunchak。感谢本书的文字编辑Marilyn Smith,无论我如何殚精竭虑以求文字的清晰与一致,此君总能从鸡蛋里挑出骨头。本书的版面和设计由Riley Hoffman全面负责,在“上了同一条船”后又挑起了制作编辑的重担。Riley总是不厌其烦地满足我的请求,以求本书的排版无误——最终结果堪称完美。谢谢你。
现在,我才体味出下面这句老话的真正含义:一人写作,全家受累。感谢Britta和Cecilia对我的支持,感谢你们能容忍我因写作本书而长时间地不着家。
许可
承蒙IEEE(电气电子工程师学会)和The Open Group惠允,本书得以引用IEEE Std 1003.1,2004版以及The Open Group基础规范第6版中POSIX(可移植性操作系统接口)——信息技术标准的部分文字。可通过http://www.unix.org/version3/online.html在线查阅规范的完整版本。
WEB站点和程序示例的源码
读者可在http://man7.org/tlpi上找到更多有关本书的信息,包括本书的勘误表和程序示例源码。
反馈
欢迎读者提供BUG报告、对代码的改进建议,以及为进一步提高代码可移植性而提出的修订意见。同样欢迎读者提供针对本书内容的缺陷报告和改进阐述方式的一般性建议。当前的勘误列表参见于http://man7.org/tlpi/errata/。由于LINUX编程接口变化无常、且变更有时极为频繁,仅凭笔者一己之力很难“与时俱进”,因此读者就全新或已变更的LINUX编程接口特性所提供的反馈信息,笔者也将乐于收到,并会将其纳入本书的下一版中。
Michael Timothy Kerrisk
于德国慕尼黑和新西兰克赖斯特彻奇
2010年8月
mtk@man7.org
主题
本书将描述Linux编程接口:由UNIX操作系统的开源实现——LINUX所提供的系统调用、库函数以及其它底层接口。运行于LINUX之上的每一程序都会直接或间接地使用这些接口。这些接口允许应用程序去执行诸多任务:文件I/O、创建/删除文件和目录、创建新进程、执行程序、设置计时器、在同一计算机上发起进程或线程间通信,以及为联网计算机间的进程建立通信等等。有时,人们也将这一系列的底层接口称为系统编程接口。
尽管本书着眼于LINUX,但对于标准和可移植性问题也倍加关注。对于LINUX所特有的技术细节,以及已由POSIX和SUS标准化的UNIX普遍特性,本书会在论述中清晰地加以区分。因此,本书亦提供了对UNIX/POSIX编程接口的全面描述。对于那些在其它UNIX系统环境中编程,或者编写跨平台可移植应用程序的程序员来说,本书同样具有实用价值。
本书的读者
本书主要针对以下读者:
为LINUX系统、其他UNIX系统,或兼容于POSIX的操作系统编写应用程序的程序员和软件设计人员。
在LINUX和其它UNIX实现之间,以及LINUX和其它操作系统之间进行应用程序移植的程序员。
教/学LINUX和UNIX系统编程的高校师生。
意欲深入理解LINUX/UNIX编程接口、以及系统软件各模块实现细节的系统管理人员和高级用户(power users)。
笔者假定读者之前有过些许编程经验,但不必是在系统编程领域。此外,笔者还假定读者具备阅读C语言源码的能力,并了解如何使用shell和UNIX或LINUX的常用命令。对于不熟悉UNIX和LINUX的读者来说,阅读第二章中面向程序员对UNIX和LINUX系统基本概念所做的回顾会有所帮助。
提示:[Kernighan & Ritchie, 1988]是最具权威性的C语言参考书籍。[Harbison& Steele, 2002]一书对C语言的介绍则更为详细,并涵盖了由C99标准所带来的变化。[van der Linden, 1994]也是一本不错的C语言书籍,寓教于乐。[Peek et al., 2001]则对UNIX的使用做了简洁而完整的介绍。
贯穿本书,会以这种缩进小字体的文字形式用于旁注,其内容包括:基本原理、实现细节、背景信息、史上轶闻以及与正文相关的其它辅助主题。
LINUX和UNIX
其它UNIX实现的大多数特性同样见诸于Linux,反之亦然。有鉴于此,本书本可只关注于标准UNIX(即POSIX)的系统编程。编写可移植的应用程序固然是值得追求的目标,但描述LINUX对标准UNIX编程接口的扩展也同样重要。LINUX的广受欢迎只是原因之一,而有时出于性能方面的考虑,或是需要访问标准UNIX编程接口所不支持的功能时,使用非标准扩展(正因如此,所有UNIX实现都提供有非标准扩展)就显得至为重要,此为原因之二。
综上所述,在构思本书时,笔者不但力图使其对在各种UNIX实现中编程的程序员有所帮助,还全面介绍了LINUX专有的编程特性。这包括:
. epoll ,获取文件I/O事件通知的一种机制。
. inotify ,监控文件和目录变化的一种机制。
.capabilities, 为进程赋予超级用户的部分权限的一种机制。
.扩展属性
. i-node标记
. clone()系统调用
. /proc文件系统
.在文件I/O、信号、计时器、线程、共享库、进程间通信以及套接字方面LINUX所专有的实现细节。
本书的用途和组织结构
本书主要具备以下两种用途:
.作为Linux/UNIX编程接口的入门教程。读者可循序阅读本书。后续各章内容均构建于之前诸章素材的基础之上,伴之以尽可能简短的前向引用。
.作为Linux/UNIX编程接口的参考大全。读者可以根据书后的详细索引和正文中频繁出现的交叉引用,随机选择阅读主题。
本书各章可分为以下几个部分:
1、背景知识及概念:UNIX、C语言以及LINUX的历史回顾,以及对UNIX标准的概述(第一章);以程序员为对象,对LINUX和UNIX的概念进行介绍(第二章);LINUX和UNIX系统编程的基本概念(第三章)。
2、系统编程接口的基本特性:文件I/O(四、五两章);进程(第六章);内存分配(第七章);用户和组(第八章);进程凭证(process credential)(第九章);时间(第十章);系统限制和选项(第十一章);以及获取系统和进程信息(第十二章)。
3、系统编程接口的高级特性:文件I/O缓冲(第十三章);文件系统(第十四章);文件属性(第十五章);扩展属性(第十六章);访问控制列表(第十七章);目录和链接(第十八章);监控文件事件(第十九章);信号(signals)(二十至二十二章);以及计时器(第二十三章)。
4、进程、程序及线程:进程的创建、终止,监控子进程,执行程序(二十四至二十八章);以及POSIX线程(二十九至三十三章)。
5、进程及程序的高级主题:进程组、会话以及任务控制(第三十四章);进程优先级和进程调度(第三十五章);进程资源(第三十六章);守护进程(第三十七章);编写安全的特权程序(第三十八章);能力(capability)(第三十九章);登陆记账(第四十章);以及共享库(四十一和四十二两章)。
6、进程间通信(IPC):IPC概览(第四十三章);管道和FIFO(第四十四章);系统V IPC消息队列、信号(semaphore)及共享内存(四十五至四十八章);内存映射(第四十九章);虚拟内存操作(第五十章);POSIX消息队列、信号及共享内存(五十一至五十四章);以及文件锁定(第五十五章)。
7、套接字和网络编程:使用套接字的IPC和网络编程(五十六至六十一章)。
8、高级I/O主题:终端(第六十二章);其它I/O模型(第六十三章);以及伪终端(第六十四章)。
程序示例
本书会以简短而完整的程序示例来描述大部分编程接口,以期读者通过命令行方便地体验这些程序,从而了解各种不同系统调用和库函数的运作方式。因此,本书包含了大量代码示例——约15000行C语言代码和shell会话记录。
虽然阅读并执行上述示例代码是学习LINUX编程接口的一个不错的起点,但巩固本书所述概念最为有效的方式还是动手编写代码——无论是修改示例程序以验证自己的编程思路,还是编写全新的程序。
书中所有源代码均可从本书网站上下载。网站所发布的源码中还包含了不少未见诸于本书的额外程序。这些程序的用途和详细信息在源码注释中均有描述。源码中还提供了Makefile,用来构建相应的程序,附带的README文件则提供了相应程序的具体细节。
在GNU Affero通用公共许可证(Affero GPL)版本3条款的约束之下,可自由地再行发布和修改本书源码,源代码中也提供了一份GNU Affero GPL版本3的文件副本。
习题
本书各章大都会在结尾处附有一组习题,其中一部分会利用书中的程序示例进行各种试验。另一些习题中的问题则与本章所讨论的概念相关,而其它习题则是引导读者亲自动手编程,意在巩固读者对所学内容的理解。附录F会有选择地给出部分习题的答案。
标准和可移植性
本书自始至终都对可移植性问题予以了特殊关注。对相关标准的引用在书中会频繁出现,尤其是POSIX.1-2001和SUSv3的联合标准(译者注:其实是一套标准的两种称谓,下同)。此外,本书还包括了该标准最新版本(POSIX.1-2008与SUSv4联合标准)的变动细节。(由于SUSv3(较之于之前的版本)做了大范围的修订,并且在写作本书之际,SUSv3依然是影响最为广泛的UNIX标准,故而本书对标准的讨论一般都以SUSv3为框架,并会注明其与SUSv4之间的差别。然而,对读者来说,除非另有说明,与SUSv3规范有关的论述同样适用于SUSv4。)
对于那些尚未标准化的特性,本书会列出与其它UNIX实现间的差异范围。此外,本书也会强调那些独具LINUX实现特色的主要特性,以及LINUX和其它UNIX实现之间在系统调用和库函数方面的细微差别。任何特性,凡未注明为LINUX所专有,读者通常可将其视同为大部分或所有UNIX实现的标准特性。
书中的编程示例(除了注明为LINUX所专有的特性)大多已在Solaris、FreeBSD、 Mac OS X、Tru64 UNIX以及HP-UX中的所有或部分系统上进行了测试。为了改进针对其中某些系统的可移植性,本书的WEB站点还为特定编程示例提供了其它版本,额外的代码并未在本书中出现。
LINUX内核和C语言库版本
本书主要着眼于Linux 2.6.x,撰写本书之际,这一内核版本的使用也最为广泛。本书同样涵盖了LINUX2.4内核的详细信息,也会适时指明LINUX2.4和2.6内核间特性的差异。凡是见诸于LINUX2.6.x系列中的新特性,笔者均会标出其(首度)出现的确切内核版本号(例如,2.6.34)。
至于C语言库,本书会重点关注GNU C库(glibc)版本2。本书也会适时指出glibc 2.x版本之间所存在的差异。
本书付梓之际,LINUX内核版本2.6.35刚刚问世,不久又发布了glibc版本2.12。本书目前的论述涵盖了以上两种软件的这两个版本。本书出版之后,LINUX和glibc接口所发生的变化会在本书的WEB站点上公布。
在其它语言中调用编程接口
虽然本书的程序示例都以C语言编写而成,但读者也能使用其它编程语言来调用本书所描述的编程接口,这些语言既包括编译语言,例如:C++、Pascal、Modula、Ada、FORTRAN和D语言;也包括脚本语言,例如:Perl、Python和Ruby(如要使用java,则需另辟蹊径,可参阅[Rochkind, 2004])。需要运用不同的技术以获取必要的常量定义和函数申明(C++除外),而按C语言链接惯例所约定的方式来传递函数参数可能也需要额外的工作投入。虽然实现起来有差异,但基本原理却都相同,即便读者在使用其他语言进行编程,本书所含信息对他们也同样适用。
关于作者
本人于1987年开始使用UNIX和C语言。当时,笔者连续几个礼拜都泡在一台HP Bobcat工作站旁,陪伴我的只有Marc Rochkind所著《Advanced UNIX Programming》一书的第一版,和一本最终被翻得卷了边的C shell手册的印刷本。投入时间阅读文档(如果有的话),并编写一些小型的(规模可逐渐变大)测试程序进行试验,直至自己对软件的理解感到信心满满——这是笔者当时所采用的编程学习方法,并一直沿用至今——笔者也向任何试水新型软件技术的人们推荐这一做法。依笔者拙见,从长远来看,这种自学方法能够大大节约时间。本书所载的许多编程示例正是在这一学习方法的激励之下设计而成。
笔者的主要身份是软件工程师和设计师。然而,笔者同样好为人师,并已在学术或商业领域有过数年的教学经验。笔者还开设过多门为期一周的UNIX系统编程课程,这一经验对本书的写作也颇有影响。
笔者使用LINUX的时间大约只有与UNIX打交道的时间一半长,在这段时间里,笔者的兴趣也逐渐集中在了内核和用户空间的“分水岭”——LINUX编程接口上。这一兴趣也将笔者置身于一系列相互关联的活动中。笔者会时不时地对POSIX/SUS标准提出自己的意见并提供BUG报告;对新加入LINUX内核中的用户空间接口进行测试和设计评审(还能帮助发现并修复那些接口中的诸多代码和设计缺陷);笔者还经常在关于编程接口及其文档的主题会议上发言,并受邀多次出席LINUX内核开发者年度峰会。将上述所有事迹串接在一起的主线是笔者对LINUX领域最醒目的贡献:笔者为LINUX man-pages项目(http://www.kernel.org/doc/man-pages/)所做的工作。
LINUX手册页中的2、3、4、5以及第7部分都属于man-pages项目。这几部分也是手册页中描述编程接口的内容,这些编程接口由LINUX内核及GNU C语言库所提供——本书所要介绍的正是这方面的内容。笔者参与man-pages项目已逾十载。自2004年起,笔者成为了该项目的主要维护人,所承担的任务大致包括:撰写文档、阅读内核和C语言库源码,以及通过编程来验证文档的细节(通过为接口撰写文档来发现相关接口中的BUG,效果颇为不凡)。此外,笔者对man-pages项目的贡献也最大——在约900页的手册页中,笔者独自编写了其中的140页,并与他人合著了另外的125页。因此,在购买本书之前,读者想必已经阅读过本人的工作成果了。笔者希望这些成果能对读者有所帮助——希望本书更是如此。
致谢
没有一干人等的支持,本书的质量绝不会如此之高。我要向他们致以最诚挚的谢意。
来自世界各地的一大票技术审稿人都参与了本书初稿的阅件,找出错误,指出含糊不清的解释,对措辞、插图以及习题提出建议,测试程序,发现不为笔者所知的LINUX和其它UNIX实现间的行为差异,并不时为笔者打气助威。在本书中,笔者将许多审稿人无私奉献的真知灼见一并收纳,实则笔者的知识并非如此渊博。当然,书中的任何错误都是笔者一人之过。
无论以下技术审稿人(按姓氏字母排序)对本书手稿的审校巨细与否,篇幅多少,笔者都要向他们致以由衷的谢意:
. Christophe Blaesss是一名软件咨询工程师和培训专家,专长是LINUX在工业(实时和嵌入)方面的应用。Christophe是《Programmation système en C sous Linux》一书的作者,这本法文杰作涵盖了与本书相同的多项主题。他不吝审阅了本书的众多章节。
.David Butenhof(HP公司)是原POSIX线程工作组和SUS线程扩展工作组的成员之一,也是《Programming with POSIX Threads》一书的作者。他曾为开放软件基金会编写了最初的DCE线程参考实现,并曾担任OpenVMS and Digital UNIX线程实现的首席架构师。David审校了本书与线程相关的章节,提出了诸多改进意见,还耐心地纠正了几处笔者对POSIX线程API的理解错误。
. Geoff Clare 目前在为The Open Group开发UNIX一致性测试包,从事UNIX 标准化工作已逾20年,是 Austin Group 的6位关键参与者之一, 该组的宗旨是开发出构成POSIX.1和Single UNIX Specification基础卷的共同标准。Geoff仔细审校了手稿中与UNIX编程接口相关的内容,耐心细致地提出了众多修正和改进意见,发现了诸多潜藏于手稿中的错误,在突出标准对可移植编程的重要性方面助益颇多。
. Loïc Domaigné(当时供职于德国空中管制中心(German Air Traffic Control))是一名系统软件工程师,主要从事分布式、多并发的容错型嵌入式系统的设计和开发,此类系统对实时性有着严苛的要求。他针对SUSv3中与线程规范有关的内容发表过评论和建议,在多个网上技术论坛中古道热肠、诲人不倦,无私的分享自己的编程心得。Loïc细致地审校了本书与线程有关的章节,以及多处其它内容。除了编写若干精巧的程序来验证LINUX线程实现的细节以外,他还倾注了巨大的热情并鼓励笔者,提出了许多建议以改进本书整体的表现形式。
. Gert Döring mgetty和sendfax程序的开发者,这对“双子星座”也是LINUX/UNIX系统上使用最为广泛的开源传真软件包。最近,他主要忙于搭建并维护基于IPv4和IPv6的大型网络,其肩负的主要任务是:与全欧洲的同事一起定义有效的网络策略,以确保Internet基础设施顺畅运行。Gert审校了本书与终端、登陆记账、进程组、会话以及任务控制有关的章节,并提供了大量有用的反馈信息。
. Wolfram Gloger 是一名IT顾问,过去十五年来,他参与过许多自由和开源软件项目(Free and Open Source Software (FOSS))。除此之外,Wolfram还是GNU C语言库中malloc软件包的实现者。目前,他主要从事于WEB服务的开发,尤其专注于网上教学,当然,在内核和系统库方面,他仍会偶露峥嵘。Wolfram审校了本书多个章节,尤其侧重于内存方面的内容。
. Fernando Gont 是阿根廷国家科技大学(Universidad Tecnológica Nacional, Argentina)电子信息中心(Centro de Estudios de Informática (CEDI))成员。Internet工程技术(Internet engineering)是其兴趣所在,在Internet工程任务组(IETF)也能见到其活跃的身影,他还是多个RFC文档的作者。此外,Fernando还为英国CPNI(国家基础设施保护机构)中心效力,以提供对通信协议安全方面的评估,而首个完整的TCP和IP协议安全评估报告也正是由他提出。Fernando仔细审校了本书涉及网络编程的相关章节,不厌其烦地向作者解释了TCP/IP协议的诸多细节,并对相关内容提出了不少改进意见。
. Andreas Grünbacher(SUSE实验室)是为内核高手,并且是LINUX扩展属性和POSIX访问控制列表实现的作者。Andreas除了仔细审校了本书多章内容以外,还对笔者勉励有加,有时,只言片语便极有可能改变了整部书的结构。
. Christoph Hellwig LINUX存储和文件系统咨询师,也是内核方面公认的行家,参与过LINUX内核中多个部分的开发工作。在编写及审查LINUX内核补丁代码的工作之余,Christoph抽空审校了本书若干章节,并提出了诸多有益的改进和修正意见。
. Andreas Jaeger 曾领导过LINUX向x86-64架构的移植开发工作。身为GNU C语言库的开发者,他不但将该库移植到了x86-64平台,而且还促成该库符合多个领域的标准,尤其在数学库方面。他当前效力于Novell公司,是openSUSE的程序经理。Andreas审校的章节之多,超乎笔者预期。在本书的写作过程中,他除了提出诸多改进意见之外,亦给予笔者热情的鼓励。
. Rick Jones 绰号“Mr. Netperf”(HP公司联网系统的性能偏执狂),对本书的网络编程相关章节提出了宝贵意见。
. Andi Kleen (当时效力于SUSE实验室)长期以来,一直是内核方面公认的行家里手,对LINUX内核诸多不同领域贡献颇多,包括:网络、错误处理以及底层架构代码等方面。Andi对网络编程相关内容做了全面审校,拓展了笔者在LINUX TCP/IP的实现方面的眼界,此外,他还提供了许多建议,用来改善本书主题的展现形式。
. Martin Landers(google)在我有幸和他成为同事时,他还是一名学生。其后,他在短期内便集诸多技能于一身,且形象百变——软件架构师、IT培训师及职业黑客。劳Martin大驾审校本书,是笔者的荣幸。他对本书的评论和更正往往一针见血,对多章内容质量的改进功莫大焉。
.Jamie Lokier 是公认的内核高手,投身于LINUX开发已达15年之久。如今,他自封为“专家,长于解决潜伏于LINUX系统中的疑难杂症”。Jamie极其全面地审校了本书涉及内存映射、POSIX共享内存以及虚拟内存操作等方面的章节。他的审校工作不但纠正了笔者对相关主题细节方面的许多误解,相应各章的结构也得以大为改观。
. Barry Margolin 在其25年职业生涯中,从事过系统程序员、系统管理员以及技术支持工程师。当前,他作为一名系统性能工程师,供职于Akamai技术公司。在各种讨论UNIX和Internet技术主题的网上论坛中,他频频现身、威名素著。他还是多本相关技术主题书籍的技术审稿人。Barry审校了本书若干章节,并提出了诸多改进意见。
. Paul Pluzhnikov(google)之前曾是Insure++内存调试工具的技术带头人和主要开发者。有时,他也会以GDB黑客的身份现身,在网上论坛里积极地回复有关调试、内存分配、共享库以及运行时环境方面的问题。Paul审校了本书多章内容,提出了许多宝贵意见。
. John Reiser (会同Tom London),实现了UNIX向32位架构移植的早期版本之一: VAX-11/780。他还是mmap()系统调用的编写者。John审校了本书多章内容(自然也包括mmap()所在的章节)。他所提供的大量历史洞见、及其对技术透彻地阐释为本书相关章节增色不少。
. Anthony Robins(新西兰Otago大学计算机科学副教授)笔者30年的密友,本书某些章节的第一个读者,也是最早提出宝贵意见的技术审校者,在本书的写作过程中,一直给予笔者以激励。
. Michael Schröder (Novell) GNU screen程序的主要开发者之一,这项编程工作已令其在终端驱动程序的实现方面达到了“巨细靡遗,了如指掌”的境界。Michael除了审校本书与终端和伪终端有关的章节以外,还针对进程组、会话以及任务控制等章节提出了极为有益的反馈意见。
. Manfred Spraul 曾从事过LINUX内核中(包括但不限于)IPC的开发工作,不吝审校了本书与IPC相关的若干章节,并提出了许多改进意见。
. Tom Swigg 笔者在DEC从事培训工作时曾与他共事,作为本书最早的技术审校者之一,他对许多章节都提出了重要的反馈意见。Tom从事软件工程师和IT培训师的工作已逾25年,目前就职于伦敦南岸大学(London South Bank University),在Vmware环境下从事LINUX编程和技术支持工作。
. Jens Thoms Törring 继承了物理学家改学编程的优良传统,大批开源的设备驱动程序和其它软件都出自他手。Jens审校的章节之多,在技术方面跨度之大,着实令人瞠目,他对各章内容的改进都提出了独特而又弥足珍贵的见解。
还有许多其他技术审稿人也审校了本书的不同内容,并提出了诸多宝贵意见。在此,笔者向以下一干技术审稿人表示感谢(以姓氏字母顺序排列):George Anzinger (MontaVista Software), Stefan Becher, Krzysztof Benedyczak, Daniel Brahneborg, Andries Brouwer, Annabel Church, Dragan Cvetkovic, Floyd L. Davidson, Stuart Davidson (Hewlett-Packard Consulting), Kasper Dupont, Peter Fellinger (jambit GmbH), Mel Gorman (IBM), Niels Göllesch, Claus Gratzl, Serge Hallyn (IBM),Markus Hartinger (jambit GmbH), Richard Henderson (Red Hat), Andrew Josey (The Open Group), Dan Kegel (Google), Davide Libenzi, Robert Love (Google), H.J. Lu (Intel Corporation), Paul Marshall, Chris Mason, Michael Matz (SUSE),Trond Myklebust, James Peach, Mark Phillips (Automated Test Systems), Nick Piggin(Novell SUSE实验室), Kay Johannes Potthoff, Florian Rampp, Stephen Rothwell (IBM Linux技术中心), Markus Schwaiger, Stephen Tweedie (Red Hat), Britta Vargas, Chris Wright, Michal Wronski以及 Umberto Zamuner。
除了技术审稿人之外,笔者还得到了各界人士及组织在其它方面的帮助。
我要感谢以下一干人等为我解答技术难题,他们是:Jan Kara、Dave Kleikamp和Jon Snader。我要感谢Claus Gratzl和Paul Marshall在系统管理方面对我的帮助。
我要感谢LINUX基金会(LF)。2008年间,LF资助我作为一名全职研究人员参与man-pages项目、并从事LINUX编程接口的测试和设计评审工作。虽然LF全职研究员的身份不能为本书的写作提供直接的资金支持,但却使笔者得以养家糊口,这一助力初衷在于令我全身心投入对LINUX编程接口的测试以及对文档的编纂工作,却也惠及笔者的 “私活”。抛开公事不谈,我要感谢Jim Zemlin——我在LF的“接口”人。还要感谢LF技术咨询委员会的一干专家,感谢他们聘我为全职研究员。
感谢Alejandro Forero Cuervo对本书书名的建议!
25年多前,在我为第一个学位拼搏之时,Robert Biddle激起了我对UNIX、C,以及Ratfor的兴趣,谢谢你,老兄。虽然以下一干人等对本书并无直接干系,但当我在新西兰坎特伯雷大学攻读第二学位时,他们就鼓励我在写作道路上坚持走下去,在此,我要向他们表示感谢,他们是:Michael Howard, Jonathan Mane-Wheoki, Ken Strongman, Garth Fletcher, Jim Pollard,以及Brian Haig。
由Richard Stevens所著的几部关于UNIX编程和TCP/IP方面的杰作,数年来一直被我辈程序员奉为技术的神奇源泉,只可惜先贤已逝。凡是读过上述书籍的读者势必会注意到,本书与Richard Stevens的那几本巨著看起来有些相似。这并非偶然。在构思本书时,笔者曾从较为宏观的角度就书籍设计反复斟酌,可最终发现Richard Stevens所采用的方法才是正解,正因如此,本书采用了与其相同的展示方式。
感谢下列人士和组织为我提供UNIX系统,使我得以运行测试程序,并验证其它UNIX实现的细节:感谢Anthony Robins和Cathy Chandra在新西兰Otago大学所提供的多种UNIX测试系统;感谢Martin Landers, Ralf Ebner和 Klaus Tilk在德国慕尼黑技术大学(Technische Universität)所提供的多种UNIX测试系统;感谢HP公司在Internet上免费开放他们的testdrive系统;感谢Paul de Weerd使我得以访问OpenBSD系统。
要衷心感谢两家慕尼黑公司及其老板,这两家公司除了为我提供了工作机会(还是弹性工作制)和热情的同事,还格外开恩,允许我在写作本书之时使用他们的办公室。感谢exolution有限公司的Thomas Kahabka和Thomas Gmelch,特别要感谢jambit 有限公司的Peter Fellinger和Markus Hartinger。
感谢下列人士对我提供的各种帮助,他们是:Dan Randow, Karen Korrel, Claudio Scalmazzi, Michael Schüpbach, and Liz Wright。感谢Rob Suisted和Lynley Cook为封面和封底所提供的照片。
感谢下列人士以不同方式给笔者以鼓励和支持,他们是:Deborah Church, Doris Church和Annie Currie。
感谢No Starch出版社大队人马为这一庞大的创作项目所提供的各种帮助。Bill Pollock从项目之初就一直秉持直言不讳的风格,始终对本书的完成充满信心,并耐心地关注着项目的进展,我要对他表示感谢。感谢本书最初的责编Megan Dunchak。感谢本书的文字编辑Marilyn Smith,无论我如何殚精竭虑以求文字的清晰与一致,此君总能从鸡蛋里挑出骨头。本书的版面和设计由Riley Hoffman全面负责,在“上了同一条船”后又挑起了制作编辑的重担。Riley总是不厌其烦地满足我的请求,以求本书的排版无误——最终结果堪称完美。谢谢你。
现在,我才体味出下面这句老话的真正含义:一人写作,全家受累。感谢Britta和Cecilia对我的支持,感谢你们能容忍我因写作本书而长时间地不着家。
许可
承蒙IEEE(电气电子工程师学会)和The Open Group惠允,本书得以引用IEEE Std 1003.1,2004版以及The Open Group基础规范第6版中POSIX(可移植性操作系统接口)——信息技术标准的部分文字。可通过http://www.unix.org/version3/online.html在线查阅规范的完整版本。
WEB站点和程序示例的源码
读者可在http://man7.org/tlpi上找到更多有关本书的信息,包括本书的勘误表和程序示例源码。
反馈
欢迎读者提供BUG报告、对代码的改进建议,以及为进一步提高代码可移植性而提出的修订意见。同样欢迎读者提供针对本书内容的缺陷报告和改进阐述方式的一般性建议。当前的勘误列表参见于http://man7.org/tlpi/errata/。由于LINUX编程接口变化无常、且变更有时极为频繁,仅凭笔者一己之力很难“与时俱进”,因此读者就全新或已变更的LINUX编程接口特性所提供的反馈信息,笔者也将乐于收到,并会将其纳入本书的下一版中。
Michael Timothy Kerrisk
于德国慕尼黑和新西兰克赖斯特彻奇
2010年8月
mtk@man7.org