第2章U N I X标准化及实现
2.1 引言
U N I X和C程序设计语言的标准化工作已经做了很多。虽然U N I X应用程序在不同的U N I X
版本之间进行移植相当容易,但是8 0年代U N I X版本的剧增以及它们之间差别的扩大导致很多
大用户(例如美国政府)要求对其进行标准化。
本章将介绍正在进行的各种标准化工作,然后讨论这些标准对本书所列举的实际U N I X实
现的影响。所有标准化工作的一个重要部分是对每种实现必须定义的各种限制的说明,所以我
们将说明这些限制以及确定它们值的多种方法。
2.2 UNIX标准化
2.2.1 ANSI C
1 9 8 9年后期,C程序设计语言的A N S I标准X 3 . 1 5 9 - 1 9 8 9得到批准〔ANSI 1989〕。此标准已
被采用为国际标准ISO/IEC 9899:1990。A N S I是美国国家标准学会,它是由制造商和用户组成
的非赢利性组织。在美国,它是全国性的无偿标准交换站,在国际标准化组织( I S O )中是代表
美国的成员。
ANSI C标准的意图是提供C程序的可移植性,使其能适合于大量不同的操作系统,而不只
是UN I X。此标准不仅定义了C程序设计语言的语法和语义,也定义了其标准库〔ANSI 1989第
4章;Plauger 1992;Kernighan及Ritchie 1988中的附录B〕。因为很多新的U N I X系统(例如本书
介绍的几个U N I X系统)都提供C标准中说明的库函数,所以此库对我们来讲是很重要的。
按照该标准定义的各个头文件,可将该库分成1 5区。表2 - 1中列出了C标准定义的头文件,
以及下面几节中说明的另外两个标准( P O S I X . 1和X P G 3 )定义的头文件。在其中也列举了S V R 4
和4 . 3 + B S D所支持的头文件。本章也将对这两种U N I X实现进行说明。
表2-1 由各种标准和实现定义的头文件
头文件
标准实现
说明
ANSI C P O S I X . 1 X P G 3 S V R 4 4 . 3 + B S D
< a s s e r t . h > • • • 验证程序断言
< c p i o . h > • • c p i o归档值
< c t y p e . h > • • • 字符类型
< d i r e n t . h > • • • • 目录项( 4 . 2 1节)
< e r r n o . h > • • • 出错码( 1 . 7节)
< f c n t l . h > • • • • 文件控制( 3 . 1 3节)
< f l o a t . h > • • • 浮点常数
< f t w . h > • • 文件树漫游( 4 . 2 1节)
(续)
头文件
标准实现
说明
ANSI C P O S I X . 1 X P G 3 S V R 4 4 . 3 + B S D
< g r p . h > • • • • 组文件( 6 . 4节)
< l a n g i n f o . h > • • 语言信息常数
< l i m i t s . h > • • • 实施常数( 2 . 5节)
< l o c a l e . h > • • • 本地类别
< m a t h . h > • • • 数学常数
< n l _ t y p e s . h > • • 消息类别
< p w d . h > • • • • 口令文件( 6 . 2节)
< r e g e x . h > • • • 正则表达式
< s e a r c h . h > • • 搜索表
< s e t j m p . h > • • • 非局部g o t o ( 7 . 1 0节)
< s i g n a l . h > • • • 信号(第1 0章)
< s t d a r g . h > • • • 可变参数表
< s t d d e f . h > • • • 标准定义
< s t d i o . h > • • • 标准I / O库(第5章)
< s t d l i b . h > • • • 公用函数
< s t r i n g . h > • • • 字符串操作
< t a r . h > • • t a r归档值
< t e r m i o s . h > • • • • 终端I / O (第11章)
< t i m e . h > • • • 时间和日期( 6 . 9节)
< u l i m i t . h > • • 用户限制
< u n i s t d . h > • • • • 符号常数
< u t i m e . h > • • • • 文件时间( 4 . 1 9节)
< s y s / i p c . h > • • • I P C ( 1 4 . 6节)
< s y s / m s g . h > • • 消息队列( 1 4 . 7节)
< s y s / s e m . h > • • 信号量( 1 4 . 8节)
< s y s / s h m . h > • • • 共享存储( 1 4 . 9节)
< s y s / s t a t . h > • • • • 文件状态(第4章)
< s y s / t i m e s . h > • • • • 进程时间( 8 . 1 5节)
< s y s / t y p e s . h > • • • • 原系统数据类型( 2 . 7节)
< s y s / u t s n a m e . h > • • • 系统名( 6 . 8节)
< s y s / w a i t . h > • • • • 进程控制( 8 . 6节)
2.2.2 IEEE POSIX
P O S I X是一个由I E E E (电气和电子工程师学会)制订的标准族。P O S I X的意思是计算机环境
的可移植操作系统界面(Portable Operating System Interface for Computer Environment)。它原来
指的只是I E E E标准1 0 0 3 . 1 - 1 9 8 8 (操作系统界面),但是, I E E E目前正在制订P O S I X族中的其他
有关标准。例如, 1 0 0 3 . 2将是针对s h e l l和公用程序的标准, 1 0 0 3 . 7将是系统管理方面的标准。
在1 0 0 3工作组中至少有1 5个子委员会。
与本书相关的是1 0 0 3 . 1操作系统界面标准,该标准定义了“ P O S I X依从的”操作系统必须
1 8 U N I X环境高级编程
下载
提供的服务。虽然1 0 0 3 . 1标准是以U N I X操作系统为基础的,但是它又不仅仅限于U N I X和类似
于U N I X的系统。确实,有些供应专有操作系统的制造商也声称这些系统将依从P O S I X (同时还
保有它们的所有专有功能)。
由于1 0 0 3 . 1标准说明了一个界面( i n t e r f a c e)而不是一种实现( i m p l e m e n t a t i o n),所以并
不区分系统调用和库函数。所有在标准中的例程都被称为函数。
标准是不断演变的, 1 0 0 3 . 1标准也不例外。该标准的1 9 8 8版,IEEE 1003.1-1988经修改后
递交给I S O,没有增加新的界面或功能,但修改了文本。最终的文档作为IEEE Std.1003.1-1990
正式出版〔IEEE 1990 〕,这也就是国际标准ISO/IEC 9945-1:1990 。该标准通常被称之为
P O S I X . 1,本书将使用此标准。
IEEE 1003.1工作组此后对其又作了更多修改,它们在1 9 9 3年被批准。这些修改(现在称之
为1 0 0 3 . 1 a )应由I E E E作为I E E E标准1 0 0 3 . 1 - 1 9 9 0的附件出版,这些修改也对本书有所影响,主要
是因为伯克利风格的符号链接很可能将被加到标准中作为一种要求的功能。这些修改也很可能
成为ISO/IEC 9945-1:1990的一个附录。本书将用注释的方法来说明P O S I X . 1的1 0 0 3 . 1 a版本,指
出哪些功能很可能会加到1 0 0 3 . 1 a中。
P O S I X . 1没有包括超级用户这样的概念。代之以规定某些操作要求“适当的优先权”,
P O S I X . 1将此术语的定义留由具体实现进行解释。某些符合国防部安全性指导原则要求的U n i x
系统具有很多不同的安全级。本书仍使用传统的U N I X术语,并指明要求超级用户特权的操作。
2.2.3 X/Open XPG3
X / O p e n是一个国际计算机制造商组织。它提出了一个7卷本可移植性指南X/Open Portability
Guide (X / O p e n可移植性指南)第3版〔X/Open 1989〕,我们将其称之为X P G 3。X P G 3的第2卷
XSI System Interface and Headers(X S I系统界面和头文件)对类似U N I X的系统定义了一个界面,该
界面定义是在IEEE Std.1003.1-1988界面的基础上制订的。X P G 3包含了一些P O S I X . 1没有的功能。
例如,P O S I X . 1没有但X P G 3却有的一个功能是X / O p e n的消息设施,该设施可由应用程序
使用以在不同的语言中显示文本消息。
X P G 3界面使用了ANSI C草案而不是最后的正式标准,所以在X P G 3界面规格说明中包含
的某些功能不再使用。这些问题很可能会在将来的X P G规格说明的新版本中解决。(有关X P G 4
的工作正在进行,可能在1 9 9 3年完成。)
2.2.4 FIPS
F I P S的含义是联邦信息处理标准(Federal Information Processing Standard),这些标准是由
美国政府出版的,并由美国政府用于计算机系统的采购。F I P S 1 5 1 - 1(1 9 8 9年4月)基于I E E E
S t d . 1 0 0 3 . 1 - 1 9 8 8及ANSI C标准草案。FIPS 151-1要求某些在P O S I X . 1中可选的功能。这种F I P S
有时称为POSIX.1 FIPS。2 . 5 . 5节列出了F I P S所要求的P O S I X . 1的选择项。
POSIX.1 FIPS的影响是:它要求任一希望向美国政府销售P O S I X . 1依从的计算机系统的厂
商应支持P O S I X . 1的某些可选功能。我们将不把POSIX.1 FIPS视作为另一个标准,因为实际上
它只是一个更加严格的P O S I X . 1标准。
2.3 UNIX实现
上面一节说明了三个由各自独立的组织所制定的标准: ANSI C、IEEE POSIX以及X / O p e n
第2章U N I X标准化及实现1 9
下载
X P G 3。但是,标准只是界面的规格说明。这些标准是如何与现实世界相关连的呢?这些标准由
制造商采用,然后转变成具体实施。本书中我们感兴趣的是这些标准和它们的具体实施。
在L e ffler 等著作〔1 9 8 9〕的1 . 1节中给出了U N I X族树的详细历史和关系图。U N I X的各种
版本和变体都起源于在P D P - 11系统上运行的U N I X分时系统第6版(1 9 7 6年)和第7版(1 9 7 9年)
(通常称为V 6和V 7)。这两个版本是在贝尔实验室以外首先得到广泛应用的U N I X系统。从这棵
树上发展出三个分支:(a) AT & T分支,从此导出了系统Ⅲ和系统V (被称之为U N I X的商用版本),
( b )加州大学伯克利分校分支,从此导出4 . x B S D实现,(c) 由AT & T贝尔实验室的计算科学研究
中心不断开发的U N I X研究版本,从此导出第8、第9和第1 0版。
2.3.1 SVR4
S V R 4是AT&T UNIX系统实验室的产品,它汇集了下列系统的功能: AT&T UNIX系统V第
3 . 2版( S V R 3 . 2 ),Sun 公司的S u nO S系统,加州大学伯克利分校的4 . 3 B S D以及微软的X e n i x系统
(Xenix是在V7的基础上开发的,后来又采用了很多系统V的功能)。其源代码于1989年后期分发,
在1990年则开始向最终用户提供。SVR4符合POSIX 1003.1标准和X/Open XPG3标准。
AT & T也出版了系统V界面定义( S V I D )〔AT&T 1989〕。S V I D第3版说明了U N I X系统要达
到S V R 4质量要求所应提供的功能。如同P O S I X . 1一样,S V I D说明了一个界面,而不是一种实
现。对于一个具体实现的S V R4应查看其参考手册,以了解其不同之处〔AT&T 1990e〕。
S V R 4包含了B S D的兼容库〔AT&T 1990c〕,它提供了功能与4 . 3 B S D对应的函数和命令。但
是其中某些函数与P O S I X的对应部分有所不同,本书中所有的S V R 4实例都没有使用此兼容库。
只有你有一些早期的应用程序,又不想改变它们时,才建议使用此兼容库,新的应用程序不应
使用它。
2.3.2 4.3+BSD
B S D是由加州大学伯克利分校的计算机系统研究组研究开发和分发的。4 . 2 B S D于1 9 8 3年
问世, 4 . 3 B S D则在1 9 8 6年。这两个版本都在VA X小型机上运行。它们的下一个版本4 . 3 B S D
Ta h o e于1 9 8 8年发布,在一台称为Ta h o e的小型机上运行( L e ff l e r等的著作〔1 9 8 9〕说明了
4.3BSD Ta h o e版)。其后又有1 9 9 0年的4.3BSD Reno版,它支持很多P O S I X . 1的功能。下一个主
要版本4 . 4 B S D应在1 9 9 2年发布。
早期的B S D系统包含了AT & T专有的源代码,它们需要AT & T许可证。为了获得B S D系统的
源代码,首先需要持有AT & T的U N I X许可证。这种情况正在得到改变,在近几年来愈来愈多的
AT & T源代码正被代换成非AT & T源代码,很多加到B S D系统上的新功能也来自于非AT & T方面。
1 9 8 9年,伯克利将4.3BSD Ta h o e中很多非AT & T源代码包装成B S D网络软件,1 . 0版,并使
其成为公众可用的软件。其后则有B S D网络软件的2 . 0版,它是从4.3BSD Reno版导出的,其目
的是使大部分(如果不是全部的话) 4 . 4 B S D系统不再受AT & T许可证的限制,于是其全部源代码
都可为公众使用。
正如前言中所说明的,本书使用术语4 . 3 + B S D表示B S D系统,该系统位于
B S D网络软件2 . 0版和即将发布的4 . 4 B S D之间。
在伯克利所进行的U N I X开发工作是从P D P - 11开始的,然后转移到VA X小型机上,接着又
转移到工作站上。9 0年代早期,伯克利得到支持在广泛应用的8 0 3 8 6个人计算机上开发B S D版
2 0 U N I X环境高级编程
下载
本,结果产生了3 8 6 B S D。这一工作是由Bill Jolitz 完成的。其相关文档有发表在1 9 9 1年
D r.Dobb´s Journal上的系列文章(每月一篇)。其中很多代码出现在B S D网络软件2 . 0版中。
2.4 标准和实现的关系
我们已提及的标准定义了任一实际系统的子集。虽然IEEE POSIX正致力于在其他所需方
面(例如,网络界面,进程间的通信,系统管理)制订出标准,但在编著本书写作时,这些标准
还并不存在。
本书集中阐述了两个实际的U N I X系统:S V R 4和4 . 3 + B S D。因为这两个系统都宣称是依从
P O S I X的,所以我们一方面集中阐述了P O S I X . 1标准所要求的功能,同时又指出P O S I X和这两
个系统具体实现之间的差别。故S V R 4或4 . 3 + B S D特有的功能和例程都被清楚地标记出来。因
为X P G 3是P O S I X . 1的超集,所以我们还叙述了属于X P G 3,但不属于P O S I X . 1的功能。
应当了解, S V R 4和4 . 3 + B S D都提供了对它们早期版本功能的兼容性(例如S V R 3 . 2对
4 . 3 B S D )。例如,S V R 4对P O S I X规格说明中的非阻塞I / O ( O _ N O N B L O C K )以及传统的系统V方
法( O _ N D E L AY )都提供了支持。本书将只使用P O S I X . 1的功能,但是也会提及它所替换的是哪
一种非标准功能。与此相类似, S V R 3 . 2和4 . 3 B S D以某种方法提供了可靠信号机制,这种方法
也有别于P O S I X . 1标准。第1 0章将只说明P O S I X . 1的信号机制。
2.5 限制
有很多由实现定义的幻数和常数,其中有很多已被编写到程序中,或由特定的技术所确定。
由于大量标准化工作的努力,已有若干种可移植的方法用以确定这些幻数和实现定义的限制。
这非常有助于软件的可移植性。
以下三种类型的功能是必需的:
• 编译时间选择项(该系统是否支持作业控制)。
• 编译时间限制(短整型的最大值是什么)。
• 运行时间限制(文件名的最大字符数为多少)。
前两个,编译时间选择项和限制可在头文件中定义。程序在编译时可以包含这些头文件。
但是,运行时间限制则要求进程调用一个函数以获得此种限制值。
另外,某些限制在一个给定的实现中可能是固定的(因此可以静态地在一个头文件中定义),
而在另一个实现上则可能是变动的(需要有一个运行时间函数调用)。这种类型限制的一个例
子是文件名的最大字符数。系统V由于历史原因只允许文件名有1 4个字符,而伯克利的系统则
将此增加为2 5 5。S V R 4允许我们对每一个创建的文件系统指明是系统V文件系统还是B S D文件
系统,而每个系统有不同的限制。这就是运行时间限制的一个实例,文件名的最大长度依赖于
文件所处的文件系统。例如,根文件系统中的文件名长度限制可能是1 4个字符,而在某个其他
文件系统中文件名长度限制可能是2 5 5个字符。
为了解决这些问题,提供了三种限制:
(1) 编辑时间选择项及限制(头文件)。
(2) 不与文件或目录相关联的运行时间限制。
(3) 与文件或目录相关联的运行时间限制。
使事情变得更加复杂的是,如果一个特定的运行时间限制在一个给定的系统上并不改变,
则可将其静态地定义在一个头文件中,但是,如果没有将其定义在头文件中,则应用程序就必
第2章U N I X标准化及实现2 1
下载
须调用三个c o n f函数中的一个(我们很快就会对它们进行说明),以确定其运行时间值。
2.5.1 ANSI C限制
所有由ANSI C定义的限制都是编译时间限制。表2 - 2中列出了文件< l i m i t s . h >中定义的C标
准限制。这些常数总是定义在该头文件中,而且在一个给定系统中并不会改变。第3列列出了
ANSI C标准可接受的最小值。这用于整型长度为1 6位的系统,它使用1的补码表示。第4列列
出了整型长度为3 2位的当前系统的值,用的是2的补码表示法。注意,对不带符号的数据类型
都没有列出其最小值,它们都应为0。
我们将会遇到的一个区别是系统是否提供带符号( s i g n e d)或不带符号的( u n s i g n e d)的
字符值。从表2 - 2中的第4列可以看出,该特定系统使用带符号字符。从表中可以看到
C H A R _ M I N等于S C H A R _ M I N,C H A R _ M A X等于S C H A R _ M A X。如果系统使用不带符号字符,
则C H A R _ M I N等于0,C H A R _ M A X等于U C H A R _ M A X。
在头文件< f l o a t . h >中,对浮点数据类型也有类似的一组定义。
我们会遇到的另一个ANSI C常数是F O P E N _ M A X,这是实现保证的可同时打开的标准I / O
流的最小数,该值在头文件< s t d i o . h >中定义,其最小值是8。P O S I X . 1中的S T R E A M _ M A X(若
定义的话),则应具与F O P E N _ M A X相同的值。
ANSI C在< s t d i o . h >中也定义了常数T M P _ M A X,这是由t m p n a m函数产生的唯一文件名的
最大数。关于此常数我们将在5 . 1 3节中进行更多说明。
表2-2 <limits.h>中的整型值大小
名字说明最小可接受值典型值
C H A R _ B I T c h a r的位8 8
C H A R _ M A X c h a r的最大值(见后) 1 2 7
C H A R _ M I N c h a r的最小值(见后) -1 2 8
S C H A R _ M A X 带符号c h a r的最大值1 2 7 1 2 7
S C H A R _ M I N 带符号c h a r的最小值-1 2 7 -1 2 8
U C H A R _ M A X 不带符号c h a r的最大值2 5 5 2 5 5
I N T _ M A X i n t最大值32 767 2 147 483 647
I N T _ M I N i n t最小值-32 767 -2 147 483 648
U I N T _ M A X 不带符号的i n t的最大值65 535 4 294 967 295
S H R T _ M I N s h o r t最小值-32 767 -32 768
S H R T _ M A X s h o r t最大值32 767 32 767
U S H R T _ M A X 不带符号的s h o r t的最大值65 535 65 535
L O N G _ M A X l o n g最大值2 147 483 647 2 147 483 647
L O N G _ M I N l o n g最小值-2 147 483 647 -2 147 483 648
U L O N G _ M A X 不带符号的l o n g的最大值4 294 967 295 4 294 967 295
M B _ L E N _ M A X 一多字节字符常数中的最大字节数1 1
2.5.2 POSIX限制
P O S I X . 1定义了很多涉及操作系统实现限制的常数,不幸的是,这是P O S I X . 1中最令人迷
惑不解的部分之一。
2 2 U N I X环境高级编程
下载
它包括3 3个限制和常数,它们被分成下列八类:
(1) 不变的最小值(表2 - 3中的1 3个常数)。
(2) 不变值:S S I Z E _ M A X。
(3) 运行时间不能增加的值:N G R O U P S _ M A X。
(4) 运行时间不变的值(可能不确定):ARG_MAX, CHILD_MAX, OPEN_MAX, STREAM_
M A X以及T Z N A M E _ M A X。
(5) 路径名可变值(可能不确定):LINK_MAX, MAX_CANON, MAX_INPUT, NAME_
MAX, PAT H _ M A X以及P I P E _ B U F。
(6) 编辑时间符号常数: _ P O S I X _ S AVED_IDS, _POSIX_VERSION以及_ P O S I X _ J O B _
C O N T R O L。
(7) 执行时间符号常数: _POSIX_NO_TRUNC, _POSIX_VDISABLE 以及_ P O S I X _
C H O W N _ R E S T R I C T E D。
(8) 不再使用的常数:C L K _ T C K。
在这3 3个限制和常数中, 1 5个是必须定义的,其余的则按具体条件可定义可不定义。在
2 . 5 . 4节中,在说明sysconf, pathconf和f p a t h c o n f函数时,我们描述了可定义可不定义的限制和
常数(第4 ~ 8条)。在表2 - 7中我们总结了所有限制和常数。1 3个不变最小值则示于表2 - 3中。
表2-3 <limits.h>中的P O S I X . 1不变最小值
名字描述值
_ P O S I X _ A R G _ M A X e x e c函数的参数长度4 0 9 6
_ P O S I X _ C H I L D _ M A X 每个实际用户I D的子进程数6
_ P O S I X _ L I N K _ _ M A X 至一个文件的连接数8
_ P O S I X _ M A X _ C A N O N 终端规范输入队列的字节数2 5 5
_ P O S I X _ M A X _ I N P U T 终端输入队列的可用空间2 5 5
_ P O S I X _ N A M E _ M A X 文件名中的字节数1 4
_ P O S I X _ N G R O U P S _ M A X 每个进程同时的添加组I D数0
_ P O S I X _ O P E N _ M A X 每个进程的打开文件数1 6
_ P O S I X _ P A T H _ M A X 路径名中的字节数2 5 5
_ P O S I X _ P I P E _ B U F 能原子地写到一管道的字节数5 1 2
_ P O S I X _ S S I Z E _ M A X 能存在s s i z e _ t对象中的值32 767
_ P O S I X _ S T R E A M _ M A X 一个进程能一次打开的标准I / O流数8
_ P O S I X _ T Z N A M E _ M A X 时区名字节数3
这些值是不变的——它们并不随系统而改变。它们指定了这些特征最严格的值。一个符合
P O S I X . 1的实现应当提供至少这样大的值。这就是为什么将它们称为最小值的原因,虽然它们
的名字都包含了M A X。另外,一个可移植的应用程序不应要求更大的值。我们将在本书的适
当部分说明每一个常数的含意。
不幸的是,这些不变最小值中的某一些在实际应用中太小了。例如,目前U N I X系统每个
进程可同时打开的文件数远远超过1 6,即使是1 9 7 8 年的V 7也提供了2 0个。另外,
_ P O S I X _ PAT H _ M A X的最小值为2 5 5也太小了,路径名可能会超过这一限制。这意味着在编辑
时不能使用这两个常数_ P O S I X _ O P E N _ M A X和_ P O S I X _ PAT H _ M A X作为数组长度。
表2 - 3中的1 3个不变最小值的每一个都有一个相关的实现值,其名字是将表2 - 3中的名字删
除前缀_ P O S I X _后构成的。(这1 3个实现值是本节开始部分所列出的2 ~ 5项:不变值、运行时不
第2章U N I X标准化及实现2 3
下载
能增加的值、运行时不变的值、以及路径名可变值。)问题是所有这1 3个实现值并不能确保在
< l i m i t . h >头文件中定义。某个特定值可能不在此头文件中定义的理由是:对于一个给定进程的
实际值可能依赖于系统的存储器总量。如果没有在头文件中定义它们,则不能在编译时使用它
们作为数组边界。所以,P O S I X . 1决定提供三个运行时间函数以供调用: sysconf, pathconf以及
f p a t h c o n f,用它们可以在运行时间得到实际的实现值。但是,还有一个问题,因为其中某些值
是由P O S I X . 1定义为“可能不确定的” (逻辑上无限的),这就意味着该值没有实际上限。例如,
S V R 4的每个进程打开文件数在假想上是无限的,所以在S V R 4中O P E N _ M A X被认为是不确定
的。2 . 5 . 7节还将讨论运行时间限制不确定的问题。
2.5.3 XPG3限制
X P G 3定义了七个常数,它们总是包含在< l i m i t s . h >头文件中。P O S I X . 1则会把它们称之为
不变最小值。它们列于表2 - 4中。这些值的大多数都涉及消息。
表2-4 <limits.h>中的X P G 3不变最小值
名字说明最小可接受的值典型值
N L _ A R G M A X 调用p r i n t f和s c a n f的最大数字值9 9
N L _ L A N G M A X L A N G环境变量中的最大字节数1 4 1 4
N L _ M S G M A X 最大消息数3 2 , 7 6 7 3 2 , 7 6 7
N L _ N M A X 在N对1映射字符中的最大字节数1
N L _ S E T M A X 最大集合数2 5 5 2 5 5
N L _ T E X T M A X 消息字符串中的最大字节数2 5 5 2 5 5
N Z E R O 缺省进程优先权2 0 2 0
X P G 3也定义了值PA S S _ M A X,作为口令中的最大有效字符数(不包括终止字符n u l l),它
可能包含在< l i m i t s . h >中。P O S I X . 1则把它称之为运行时间不变的值(可能不确定),其最小可
接受的值是8。PA S S _ M A X值也可在运行时间用s y s c o n f函数取得,该函数将在2 . 5 . 4节中说明。
2.5.4 sysconf、pathconf 和fpathconf 函数
我们已列出了一个实现必须支持的各种最小值,但是怎样才能找到一个特定系统实际支持
的限制值呢? 正如前面提到的,某些限制值在编译时是可用的,而另外一些则必须在运行时确
定。我们也曾提及在一个给定的系统中某些限制值是不会更改的,而其他则与文件和目录相关
联。运行时间限制是由调用下面三个函数中的一个而取得的。
#include <unistd.h>
long sysconf(intn a m e) ;
log pathconf(const charp a t* h n a m e,int n a m e) ;
log fpathconf(inft i l e d e s,int n a m e) ;
所有函数返回:若成功为相应值,若出错为- 1(见后)
最后两个函数之间的差别是一个用路径名作为其参数,另一个则取文件描述符作为参数。
表2 - 5中列出了这三个函数所使用的n a m e参数。以_ S C _开始的常数用作为s y s c o n f的参数,
而以_ P C _开始的常数则作为p a t h c o n f或f p a t h c o n f的参数。
2 4 U N I X环境高级编程
下载
对于pathconf 的参数p a t h n a m e , fpathconf 的参数filedes 有很多限制。如果不满足其中任何
一个限制,则结果是未定义的。
(1) _PC_MAX_CANON,_ P C _ M A X _ I N P U T以及_ P C _ V D I S A B L E所涉及的文件必须是终
端文件。
(2) _PC_LINK_MAX所涉及的文件可以是文件或目录。如果是目录,则返回值用于目录本
身(不用于目录内的文件名项)。
(3) _PC_NAME_MAX和_ P C _ N O _ T R U N C所涉及的文件必须是目录,返回值用于该目录中
的文件名。
(4) _PC_PAT H _ M A X涉及的必须是目录。当所指定的目录是工作目录时,返回值是相对路
径名的最大长度。(不幸的是,这不是我们想要知道的一个绝对路径名的实际最大长度,我们
将在2 . 5 . 7节中再回到这一问题上来。)
(5) _PC_PIPE_BUF所涉及的文件必须是管道, F I F O或目录。在管道或F I F O情况下,返回
值是对所涉及的管道或F I F O的限制值。对于目录,返回值是对在该目录中创建的任一F I F O的
限制值。
(6) _PC_CHOWN_RESTRICTED必须是文件或目录。如果是目录,则返回值指明此选择项
是否适用于该目录中的文件。
表2-5 对s y s c o n f、p a t h c o n f和f p a t h c o n f的限制及n a m e参数
限制名说明n a m e 参数
A R G _ M A X 如e x e c函数的参数最大长度(字节) _ S C _ A R G _ M A X
C H I L D _ M A X 如每个实际用户I D的最大进程数_ S C _ C H I L D _ M A X
clock ticks/ second 如每秒时钟滴答数_ S C _ C L K _ T C K
N G R O U P S _ M A X 如每个进程的最大同时添加组I D数_ S C _ N G R O U P S _ M A X
O P E N _ M A X 如每个进程最大打开文件数_ S C _ O P E N _ M A X
P A S S _ M A X 如口令中的最大有效字符数_ S C _ P A S S _ M A X
S T R E A M _ M A X 如在任一时刻每个进程的最大标准I /O 流数——如_ S C _ S T R E A M _ M A X
如若定义,则其值一定与FOPEN_MAX相同
T Z N A M E _ M A X 时区名中的最大字节数_ S C _ T Z N A M E _ M A X
_ P O S I X _ J O B _ C O N T R O L 如指明实现是否支持作业控制_ S C _ J O B _ C O N T R O L
_ P O S I X _ S A V E D _ I D S 如指明实现是否支持保存的设置-用户- I D和保存的_ S C _ S A V E D _ I D S
设置-组- I D
_ P O S I X _ V E R S I O N 如指明P O S I X . 1版本_ S C _ V E R S I O N
_ X O P E N _ V E R S I O N 如指明X P G版本(非P O S I X . 1) _ S C _ X O P E N _ V E R S I O N
L I N K _ M A X 如文件连接数的最大值_ P C _ L I N K _ M A X
M A X _ C A N O N 如在一终端规范输入队列的最大字节数_ P C _ M A X _ C A N O N
M A X _ I N P U T 如终端输入队列可用空间的字节数_ P C _ M A X _ I N P U T
N A M E _ M A X 如文件名中的最大字节数(不包括n u l l结束符) _ P C _ N A M E _ M A X
P A T H _ M A X 如相对路径名中的最大字节数(不包括n u l l结束符) _ P C _ P A T H _ M A X
P I P E _ B U F 如能原子地写到一管道的最大字节数_ P C _ P I P E _ B U F
_ P O S I X _ C H O W N _ R E S T R I C T E D 指明使用c h o w n是否受到限制_ P C _ C H O W N _ R E S T R I C T E D
_ P O S I X _ N O _ T R U N C 如指明若路径名长于N A M E _ M A X是否产生一错误_ P C _ N O _ T R U N C
_ P O S I X _ V D I S A B L E 如若定义,终端专用字符可用此值禁止_ P C _ V D I S A B L E
我们需要更详细地说明这三个函数的不同返回值。
(1) 如果n a m e不是表2 - 5第3列中的一个合适的常数,则所有这三个函数都返回- 1,并将
第2章U N I X标准化及实现2 5
下载
e r r o r设置为E I N VA L。
(2) 包含M A X的1 2个n a m e以及n a m e_ P C _ P I P E _ B U F可能或者返回该变量的值(返回值≥O ),
或者返回-1,这表示该值是不确定的,此时并不更改e r r n o的值。
(3) 对_ S C _ C L K _ T C K的返回值是每秒的时钟滴答数,以用于t i m e s函数的返回值(见8 . 1 5
节)。
(4) 对_ S C _ V E R S I O N的返回值以4位数和2位数分别表示此标准的年和月。这可能或者是
1 9 8 8 0 8 L或1 9 9 0 0 9 L,或此标准某个以后版本的值。
(5) 对_ S C _ X O P E N _ V E R S I O N的返回值表示此系统所遵从的X P G版本,其当前值是3。
(6) _SC_JOB_CONTROL和_ S C _ S AV E D _ I D S是两个可选功能。若s y s c o n f返回-1(没有更
改e r r n o)则不支持相应的功能。这两个功能也可在编译时从< u n i s t d . h >头文件中决定。
(7) 对_ P C _ C H O W N _ R E S T R I C T E D和_ P C _ N O _ T R U N C的返回值若为-1 (不改变e r r n o ),则
表示对所指定的p a t h n a m e或f i l e d e s不支持此功能。
(8) 对_ P C _ V D I S A B L E的返回值若为- 1(不改变e r r n o),则表示对所指定的p a t h n a m e或
f i l e d e s不支持此功能。若支持此功能,则返回值是被用于禁止特定终端输入字符的字符值(见
表11 - 6)。
实例
程序2 - 1用于打印所有这些限制,并处理一个限制未被定义的情况。
程序2-1 打印所有可能的s y s c o n f和p a t h c o n f值
2 6 U N I X环境高级编程
下载
我们有条件地包括了两个常数,它们已被加至P O S I X . 1,但不是IEEE Std.1003.1-1988的一
部分。表2 - 6显示了在几个不同的系统上,程序2 - 1的样本输出。我们在4 . 1 4节中可以了解到,
SVR4 S5文件系统是可以回溯到V 7的传统的系统V文件系统。U F S是伯克利快速文件系统的
S V R 4实现。
表2-6 配置限制的实例
限制SunOS 4.1.1
S V R 4
4 . 3 + B S D
S5 filesys UFS filesys
A R G _ M A X 1 048 576 5 120 5 120 20 480
C H I L D _ M A X 1 3 3 3 0 3 0 4 0
每秒时钟滴答6 0 1 0 0 1 0 0 6 0
N G R O U P S _ M A X 1 6 1 6 1 6 1 6
O P E N _ M A X 6 4 6 4 6 4 6 4
_ P O S I X _ J O B _ C O N T R O L 1 1 1 1
_ P O S I X _ S A V E D _ I D S 1 1 1 未定义
_ P O S I X _ V E R S I O N 198 808 198 808 198 808 198 808
M A X _ C A N O N 2 5 6 2 5 6 2 5 6 2 5 5
M A X _ I N P U T 2 5 6 5 1 2 5 1 2 2 5 5
_ P O S I X _ V D I S A B L E 0 0 0 2 5 5
L I N K _ M A X 32 767 1 000 1 000 32 767
第2章U N I X标准化及实现2 7
下载
argv[1], _PC_CHOWN_RESTRICTED);
(续)
限制SunOS 4.1.1
S V R 4
4 . 3 + B S D
S5 filesys UFS filesys
N A M E _ M A X 2 5 5 1 4 2 5 5 2 5 5
P A T H _ M A X 1 024 1 024 1 024 1 024
P I P E _ B U F 4 096 5 120 5 120 5 1 2
_ P O S I X _ N O _ T R U N C 1 未定义1 1
_ P O S I X _ C H O W N _ R E S T R I C T E D 1 未定义未定义1
2.5.5 FIPS 151-1要求
FIPS 151-1标准(我们已在2 . 2 . 4节中提及)由于要求下列功能,所以它比P O S I X . 1标准更严:
• 要求下列P O S I X . 1可选功能:_POSIX_JOB_CONTROL, _POSIX_SAVED_IDS, _POSIX_
NO_TRUNC, _POSIX_CHOWN_RESTRICTED和_ P O S I X _ V D I S A B L E。
• NGROUPS_MAX的最小值是8。
• 新创建的文件或目录的组I D应设置为它所在目录的组I D(4 . 6节将说明此功能)。
• 已传输了一些数据后,若r e a d或w r i t e被一个捕捉到的信号所中断,则这些函数应返回已
被传输的字节数(1 0 . 5节将讨论被中断的系统调用)。
• 登录s h e l l应定义环境变量H O M E和L O G N A M E。
因为美国政府购买了很多计算机系统,所以大多数P O S I X的制造商都将支持这些增加的
F I P S要求。
2.5.6 限制总结
我们已说明了很多限制和幻常数,其中某些必须包含在头文件中,某些可选地包含在头文
件中,其他则可在运行时决定。表2 - 7以字母顺序总结了所有这些常数以及得到它们值的各种
方法。以_ S C _开始的运行时间名字是s y s c o n f函数的参数,以_ P C _开始的名字是p a t h c o n f和
f p a t h c o n f函数的参数,如果它有最小值,则也将其列于其中。
注意,表2 - 3中的1 3个P O S I X . 1不变最小值示于表2 - 7中的最右一列。
表2-7 编译时间和运行时间限制总结
编译时间
常数名
头文件要求否
运行时间名最小值
A R G _ M A X < l i m i t s . h > 可选_ S C _ A R G _ M A X _ P O S I X _ A R G _M A X=4 0 9 6
C H A R _ B I T < l i m i t s . h > 要求8
C H A R _ M A X < l i m i t s . h > 要求1 2 7
C H A R _ M I N < l i m i t s . h > 要求0
C H I L D _ M A X < l i m i t s . h > 可选_ S C _ C H I L D _ M A X _ P O S I X _ C H I L D _ M A X =6
每秒时钟滴答_ S C _ C L K _ T C K
F O P E N _ M A X < s t d i o . h > 要求8
I N T _ M A X < l i m i t s . h > 要求32 767
I N T _ M I N < l i m i t s . h > 要求-32 767
L I N K _ M A X < l i m i t s . h > 可选_ P C _ L I N K _ M A X _ P O S I X _ L I N K _M A X=8
L O N G _ M A X < l i m i t s . h > 要求2 147 483 647
2 8 U N I X环境高级编程
下载
(续)
编译时间
常数名
头文件要求否
运行时间名最小值
L O N G _ M I N < l i m i t s . h > 要求-2 147 483 647
M A X _ C A N O N < l i m i t s . h > 可选_ P C _ M A X _ C A N O N _ P O S I X _ M A X _ C A N O N =2 5 5
M A X _ I N P U T < l i m i t s . h > 可选_ P C _ M A X _ I N P U T _ P O S I X _ M A X _ I N P U T =2 5 5
M B _ L E N _ M A X < l i m i t s . h > 要求
N A M E _ M A X < l i m i t s . h > 可选_ P C _ N A M E _ M A X _ P O S I X _ N A M E _M A X=1 4
N G R O U P S _ M A X < l i m i t s . h > 要求_SC_NGROUPS_MAX _ P O S I X _ N G R O U P S _ M A X =0
N L _ A R G M A X < l i m i t s . h > 要求9
N L _ L A N G M A X < l i m i t s . h > 要求1 4
N L _ M S G M A X < l i m i t s . h > 要求32 767
N L _ N M A X < l i m i t s . h > 要求
N L _ S E T M A X < l i m i t s . h > 要求2 5 5
N L _ T E X T M A X < l i m i t s . h > 要求2 5 5
N Z E R O < l i m i t s . h > 要求2 0
O P E N _ M A X < l i m i t s . h > 可选_ S C _ O P E N _ M A X _ P O S I X _ O P E N _M A X=1 6
P A S S _ M A X < l i m i t s . h > 可选_ S C _ P A S S _ M A X 8
P A T H _ M A X < l i m i t s . h > 可选_ P C _ P A T H _ M A X _ P O S I X _ P A T H _M A X=2 5 5
P I P E _ B U F < l i m i t s . h > 可选_ P C _ P I P E _ B U F _ P O S I X _ P I P E _ B U F =5 1 2
S C H A R _ M A X < l i m i t s . h > 要求1 2 7
S C H A R _ M I N < l i m i t s . h > 要求-1 2 7
S H R T _ M A X < l i m i t s . h > 要求32 767
S H R T _ M I N < l i m i t s . h > 要求-32 767
S S I Z E _ M A X < l i m i t s . h > 要求_ P O S I X _ S S I Z E _M A X=3 2 , 7 6 7
S T R E A M _ M A X < l i m i t s . h > 可选_ S C _ S T R E A M _ M A X _ P O S I X _ S T R E A M _ M A X =8
T M P _ M A X < s t d i o . h > 要求1 0 , 0 0 0
T Z N A M E _ M A X < l i m i t s . h > 可选_SC_TZNAME_MAX _ P O S I X _ T Z N A M E _MAX=3
U C H A R _ M A X < l i m i t s . h > 要求2 5 5
U I N T _ M A X < l i m i t s . h > 要求65 535
U L O N G _ M A X < l i m i t s . h > 要求4 294 967 295
U S H R T _ M A X < l i m i t s . h > 要求65 535
_ P O S I X _ C H O W N _ R E S T R I C T E D < u n i s t d . h > 可选_ P C _ C H O W N _ R E S T R I C T E D
_ P O S I X _ J O B _ C O N T R O L < u n i s t d . h > 可选_ S C _ J O B _ C O N T R O L
_ P O S I X _ N O _ T R U N C < u n i s t d . h > 可选_ P C _ N O _ T R U N C
_ P O S I X _ S A V E D _ I D S < u n i s t d . h > 可选_ S C _ S A V E D _ I D S
_ P O S I X _ V D I S A B L E < u n i s t d . h > 可选_ P C _ V D I S A B L E
_ P O S I X _ V E R S I O N < u n i s t d . h > 要求_ S C _ V E R S I O N
_ X O P E N _ V E R S I O N < u n i s t d . h > 要求_ S C _ X O P E N _ V E R S I O N
2.5.7 未确定的运行时间限制
我们已提及表2 - 7中的某些值可能是未确定的,这些值在第三列中标记为可选的( o p t i o n a l ),
其名字中包含M A X,或P I P E _ B U F。我们遇到的问题是如果这些值没有在头文件< l i m i t s . h >中定
义,那么在编译时我们也就不能使用它们。但是,如果它们的值是未确定的,那么在运行时它
们可能也是未定义的。让我们观察两个特殊的例子—为一个路径名分配存储器,以及决定文
件描述符的数目。
第2章U N I X标准化及实现2 9
下载
1. 路径名
很多程序需要为路径名分配存储器,一般来说,在编译时就为其分配了存储器,而且使用
了各种幻数(其中很少是正确的)作为数组长度: 2 5 6,5 1 2,1 0 2 4或标准I / O常数B U F S I Z。
4 . 3 B S D头文件< s y s / p a r a m . h >中的常数M A X PAT H L E N是正确值,但是很多4 . 3 B S D应用程序并
未用它。
P O S I X . 1试图用PAT H _ M A X值来帮助我们,但是如果此值是不确定的,那么仍是毫无帮助
的。程序2 - 2是一个全书都将使用的为路径名动态地分配存储器的函数。
如若在< l i m i t s . h >中定义了常数PAT H _ M A X ,那么就没有任何问题,如果没有,则需调用
p a t h c o n f。因为p a t h c o n f的返回值是把第一个参数视为基于工作目录的相对路径名。所以指定根
为第一个参数,并将得到的返回值加1作为结果值。如果p a t h c o n f指明PAT H _ M A X是不确定的,
那么我们就只得猜测某个值。调用m a l l o c时的+ 1是为了在尾端加n u l l字符(PAT H _ M A X没有考
虑它)。
处理不确定结果情况的正确方法与如何使用分配到的存储空间有关。例如,如果我们为
g e t c w d调用分配空间(返回当前工作目录的绝对路径名,见4 . 2 2节),而分配到的空间太小,
则返回一个出错, e r r n o设置为E R A N G E。然后可调用r e a l l o c以增加分配空间(见7 . 8节和练习
4 . 1 8 )并再试。不断重复此操作,直到g e t c w d调用成功执行。
程序2-2 为路径名动态地分配空间
3 0 U N I X环境高级编程
下载
2. 最大打开文件数
在精灵进程(是在后台运行,不与终端相连接的一种进程)中一个常见的代码序列是关闭所
有打开文件。某些程序中有下列形式的代码序列:
#include <sys/param.h>
for (i = 0; i < NOFILE; i++)
c l o s e ( i ) ;
程序假定在< s y s / p a r a m . h >头文件中定义了常数N O F I L E。另外一些程序则使用某些< s t d i o . h >版
本提供作为上限的常数_ N F I L E。某些程序则直接将其上限值定为2 0。
我们希望用P O S I X . 1的O P E N _ M A X确定此值以提高可移植性,但是如果此值是不确定的,
则仍然有问题,如果我们使用下列代码
#include <unistd.h>
for (i = 0; i < sysconf(_SC_OPEN_MAX); i++)
c l o s e ( i ) ;
而且如果O P E N _ M A X是不确定的,那么s y s c o n f将返回-1,于是,f o r循环根本不会执行。在这
种情况下,最好的选择就是关闭所有描述符直至某个任一的限制值(例如2 5 6 )。如同上面的路
径名一样,这并不能保证在所有情况下都能正确工作,但这却是我们所能选择的最好方法。程
序2 - 3中使用了这种技术。
程序2-3 确定文件描述符数
我们可以耐心地调用c l o s e,直至得到一个出错返回,但是从c l o s e(E B A D F)出错返回
并不区分无效描述符和并未打开的描述符。如果试用此技术,而且描述符9未打开,描述符
1 0打开了,那么将停止在9上,而不会关闭1 0。d u p函数(见3 . 1 2节)在超过了O P E N _ M A X
时会返回一个特定的出错值,但是用复制一个描述符一、二百次的方法来确定此值是一种极
第2章U N I X标准化及实现3 1
下载
端的方法。
S V R 4和4 . 3 + B S D的g e t r l i m i t ( 2 )函数(见7 . 11节)以及4 . 3 + B S D的g e t d t a b l e s i z e ( 2 )
函数返回一个进程可以打开的最大描述符数,但是这两个函数是不可移植的。
O P E N _ M A X被P O S I X称为运行时间不变值,其意思是在一个进程的生命期间
其值不应被改变,但是在S V R 4和4 . 3 + B S D之下,可以调用setrlimit (2) 函数更改一
个运行进程的此值(也可用C Shell的l i m i t或Bourne shell和K o r nSh e l l的u l i m i t命令
更改)。如果系统支持这种功能,则可以将程序2 - 3更改为每次调用此程序时就调
用s y s c o n f,而不只是第一次调用此程序时。
2.6 功能测试宏
正如前述,在头文件中定义了很多P O S I X . 1和X P G 3的符号。但是除了P O S I X . 1和X P G 3定
义外,大多数实现在这些头文件中也加上了它们自己的定义。如果在编译一个程序时,希望它
只使用P O S I X定义而不使用任何实现定义的限制,那么就需定义常数_ P O S I X _ S O U R C E,所有
P O S I X . 1头文件中都使用此常数。当该常数定义时,就能排除任何实现专有的定义。
常数_ P O S I X _ S O U R C E及其对应的常数_ X O P E N _ S O U R C E被称之为功能测试宏( f e a t u r e
test macro)。所有功能测试宏都以下划线开始。当要使用它们时,通常在c c命令行中以下列方
式定义:
cc -D_POSIX_SOURCE file.c
这使得在C程序包括任何头文件之前,定义了功能测试宏。如果我们仅想使用P O S I X . 1定
义,那么也可将源文件的第一行设置为:
#define _POSIX_SOURCE 1
另一个功能测试宏是: _ _STDC_ _,它由符合ANSI C标准的编译程序自动定义。这样就
允许我们编写ANSI C编译程序和非ANSI C编译程序都能编译的程序。例如,一个头文件可能
会是:
#ifdef _ S T D C__
void *myfunc(const char *, int);
# e l s e
void *myfunc();
# e n d i f
这样就能发挥ANSI C原型功能的长处,要注意在开始和结束处的两个连续的下划线常常
打印成一个长下划线(如同上面一个样本源代码中一样)。
2.7 基本系统数据类型
历史上,某些U N I X变量已与某些C数据类型联系在一起,例如,历史上主、次设备号存放
在一个1 6位的短整型中, 8位表示主设备号,另外8位表示次设备号。但是,很多较大的系统需
要用多于2 5 6个值来表示其设备号,于是,就需要有一种不同的技术。(确实, S V R 4用3 2位表
示设备号:1 4位用于主设备号,1 8位用于次设备号。)
头文件< s y s / t y p e s . h >中定义了某些与实现有关的数据类型,它们被称之为基本系统数据类
3 2 U N I X环境高级编程
下载
型(primitive system data type)。有很多这种数据类型定义在其他头文件中。在头文件中这些
数据类型都是用C的t y p e d e f设施来定义的。它们绝大多数都以_t 结尾。表2 - 8中列出了本书将使
用的基本系统数据类型。
表2-8 基本系统数据类型
类型说明
c a d d r _ t 内存地址( 1 2 . 9节)
c l o c k _ t 时钟滴答计数器(进程时间)(1 . 1 0节)
c o m p _ t 压缩的时钟滴答(8 . 1 3节)
d e v _ t 设备号(主和次)(4 . 2 3节)
f d _ s e t 文件描述符集( 1 2 . 5 . 1节)
f p o s _ t 文件位置( 5 . 1 0节)
g i d _ t 数值组I D
i n o _ t i节点编号( 4 . 1 4节)
m o d e _ t 文件类型,文件创建方式( 4 . 5节)
n 1 i n k _ t 目录项的连接计数( 4 . 1 0节)
o f f _ t 文件长度和位移量(带符号的)(lseek, 3.6节)
p i d _ t 进程I D和进程组I D(带符号的)(8 . 2和9 . 4节)
p t r d i f f _ t 两个指针相减的结果(带符号的)
r 1 i m _ t 资源限制( 7 . 11节)
s i g _ a t o m i c _ t 能原子地存取的数据类型( 1 0 . 1 5节)
s i g s e t _ t 信号集(1 0 . 11节)
s i z e _ t 对象(例如字符串)长度(不带符号的)(3 . 7节)
s s i z e _ t 返回字节计数的函数(带符号的)(read, write, 3.7节)
t i m e _ t 日历时间的秒计数器( 1 . 1 0节)
u i d _ t 数值用户I D
w c h a r _ t 能表示所有不同的字符码
用这种方式定义了这些数据类型后,在编译时就不再需要考虑随系统不同而变的实施细节,
在本书中涉及到这些数据类型的地方,我们会说明为什么使用它们。
2.8 标准之间的冲突
就整体而言,这些不同的标准之间配合得是相当好的。但是我们也很关注它们之间的差别,
特别是ANSI C标准和P O S I X . 1之间的差别。(因为X P G 3是一个较老的正在被修订的标准, F I P S
则是一个要求更严的P O S I X . 1。)
ANSI C定义了函数c l o c k,它返回进程使用的C P U时间,返回值是c l o c k _ t类型值。为了将
此值变换成以秒为单位,将其除以在< t i m e . h >头文件中定义的C L O C K S _ P E R _ S E C。P O S I X . 1定
义了函数t i m e s,它返回其调用者及其所有终止子进程的C P U时间以及时钟时间,所有这些值
都是c l o c k _ t类型值。IEEE Std.1003.1-1988将符号C L K _ T C K定义为每秒滴答数,上述c l o c k _ t值
都是以此度量的。而1990 POSIX.1标准中则说明不再使用, C L K _ T C K而使用s y s c o n f函数来获
得每秒滴答数,并将其用于t i m e s函数的返回值。术语是同一个,每秒滴答数,但ANSI C和
P O S I X . 1的定义却不同。这两个标准也用同一数据类型( c l o c k _ t )来保存这些不同的值,这种差
别可以在S V R 4中看到,其中c l o c k返回微秒数( C L O C K _ P E R _ S E C是一百万),而C L K _ T C K通常
是5 0、6 0或1 0 0 (与C P U类型有关)。
第2章U N I X标准化及实现3 3
下载
另一个可能产生冲突的区域是:在ANSI C标准说明函数时,ANSI C所说明的函数可能会
没有考虑到P O S I X . 1的某些要求。有些函数在P O S I X环境下可能要求有一个与C环境下不同的
实现,因为P O S I X环境中有多个进程,而C语言环境则很少会考虑宿主操作系统。尽管如此,
很多P O S I X依从的系统为了兼容性的关系也实现ANSI C函数,s i g n a l函数就是一个例子。如果
在不了解的情况下使用了S V R 4所提供的s i g n a l函数(希望编写可在ANSI C环境和较早U N I X系统
中运行的可兼容程序),那么它提供了与POSIX.1 sigaction函数不同的语义。第1 0章将对s i g n a l
函数作更多说明。
2.9 小结
在过去几年中,在U N I X不同版本的标准化方面已经取得了很大进展。本章对三个主要标
准—ANSI C、P O S I X和X P G 3—进行了说明,也分析了这些标准对本书主要关注的两个实
现:S V R 4和4 . 3 + B S D所产生的影响。这些标准都试图定义一些可能随实现而更改的参数,但
是我们已经看到这些限制并不完善。本书将涉及所有这些限制和幻常数。
在本书最后的参考书目中,说明了如何订购这些标准的方法。
习题
2 . 1在2 . 7节中提到一些基本系统数据类型可以在多个头文件中定义。例如, size_t 就在6个
不同的头文件中都有定义。由于一个程序可能包含这6个不同的头文件,但是ANSI C不允许对
同一个名字进行多次类型定义,如何处理这个矛盾呢?
2 . 2在检查系统的头文件,列出实现基本系统数据类型所用到的实际数据类型。
3 4 U N I X环境高级编程
下载