Unix之标准及实现(二)

本文主体内容来自《UNIX环境高级编程第三版》。

本文首先回顾过去近25年人们在UNIX标准化方面做出的种种努力,然后讨论这些UNIX编程标准对本书所列举的各种UNIX操作系统实现的影响。所有标准化工作的一个重要部分是对每种实现必须定义的各种限制进行说明,所以我们将说明这些限制以及确定它们值的各种方法。


UNIX标准化

ISO C

1989年下半年,C程序设计语言的ANSI标准X3.159-1989得到批准。此标准被也采纳为国际标准ISO/IEC 9899:1990。

1999年,ISO C标准被更新,并被批准为ISO/IEC 9899:1999,它显著改善了对进行数值处理的应用软件的支持。

C标准已经在2011年更新。

按照该标准定义的各个头文件可将ISO C库分成24个区。POSIX.1标准包括这些头文件以及另外一些头文件。

img

图2-1 ISO C标准定义的头文件

IEEE POSIX

POSIX是一个最初由IEEE制订的标准族。POSIX指的是可移植操作系统接口(Portable Operating System Interface)。

图2-2、图2-3以及图2-4总结了POSIX.1指定的必需的和可选的头文件。因为POSIX.1包含了ISO C标准库函数,所以它还需要图2-1中列出的各个头文件。

img

图2-2 POSIX标准定义的必需的头文件

img

图2-3 POSIX标准定义的XSI可选头文件

img

图2-4 POSIX标准定义的可选头文件

Single UNIX Specification

Single UNIX Specification(SUS,单一UNIX规范)是POSIX.1标准的一个超集,它定义了一些附加接口扩展了POSIX.1规范提供的功能。POSIX.1相当于Single UNIX Specification中的基本规范部分。

1997年,Open Group发布了Single UNIX Specification第2版。新版本增加了对线程、实时接口、64位处理、大文件以及增强的多字节字符处理等功能的支持。

Single UNIX Specification第3版(SUSv3)由Open Group在2001年发布。

2010年Single UNIX Specification第4版发布,把这个规范称为SUSv4。


UNIX系统实现

UNIX的各种版本和变体都起源于在PDP-11系统上运行的UNIX分时系统第6版(1976年)和第7版(1979年)(通常称为V6和V7)。这两个版本是在贝尔实验室以外首先得到广泛应用的UNIX系统。从这棵树上演进出以下3个分支。

(1)AT&T分支,从此引出了系统III和系统V(被称为UNIX的商用版本)。

(2)加州大学伯克利分校分支,从此引出4.xBSD实现。

(3)由AT&T贝尔实验室的计算科学研究中心不断开发的UNIX研究版本,从此引出UNIX分时系统第8版、第9版,终止于1990年的第10版。

SVR4

SVR4(UNIX System V Release 4)是AT&T的UNIX系统实验室的产品。

4.4BSD

BSD(Berkeley Software Distribution)是由加州大学伯克利分校的计算机系统研究组(CSRG)研究开发和分发的。

4.4BSD-Lite是CSRG计划开发的最后一个发行版。4.4BSD-Lite第2发行版是CSRG的最后一个BSD版本。

FreeBSD

FreeBSD基于4.4BSD-Lite 操作系统。在加州大学伯克利分校的 CSRG决定终止其在UNIX操作系统的BSD版本的研发工作,而且386BSD项目被忽视很长时间之后,为了继续坚持BSD系列,形成了FreeBSD项目。

由FreeBSD项目产生的所有软件,包括其二进制代码和源代码,都是免费使用的。

Linux

Linux是一种提供类似于UNIX的丰富编程环境的操作系统,在GNU公用许可证的指导下, Linux是免费使用的。

Linux是由Linus Torvalds在1991年为替代MINIX而研发的。

Mac OS X

与其以前的版本相比,Mac OS X使用了完全不同的技术。其核心操作系统称为“Darwin”,它基于Mach内核、FreeBSD操作系统以及具有面向对象框架的驱动和其他内核扩展的结合。Mac OS X 10.5的Intel部分已经被验证为是一个UNIX系统。

Solaris

Solaris是由Sun Microsystems(现为Oracle)开发的UNIX系统版本。它基于SVR4,在超过15 年的时间里,Sun Microsystems 的工程师对其功能不断增强。它是唯一在商业上取得成功的SVR4后裔,并被正式验证为UNIX系统。

其他UNIX系统

已经通过验证的其他UNIX版本包括:

  • AIX,IBM版的UNIX系统;

  • HP-UX,HP版的UNIX系统;

  • IRIX,Silicon Graphics版的UNIX系统;

  • UnixWare,SVR4派生的UNIX系统,现由SCO销售。


限制

UNIX 系统实现定义了很多幻数和常量,其中有很多已被硬编码到程序中,或用特定的技术确定。

以下两种类型的限制是必需的。

(1)编译时限制(例如,短整型的最大值是什么?)

(2)运行时限制(例如,文件名有多少个字符?)

编译时限制可在头文件中定义。程序在编译时可以包含这些头文件。但是,运行时限制则要求进程调用一个函数获得限制值。

为了解决这类问题,提供了以下3种限制。

(1)编译时限制(头文件)。

(2)与文件或目录无关的运行时限制(sysconf函数)。

(3)与文件或目录有关的运行时限制(pathconf和fpathconf函数)。

使事情变得更加复杂的是,如果一个特定的运行时限制在一个给定的系统上并不改变,则可将其静态地定义在一个头文件中,但是,如果没有将其定义在头文件中,应用程序就必须调用 3个conf函数中的一个,以确定其运行时的值。

ISO C限制

ISO C定义的所有编译时限制都列在头文件<limits.h>中。这些限制常量在一个给定系统中并不会改变。表中第3列列出了ISO C标准可接受的最小值。这用于16位整型的系统,用1的补码表示。第4列列出了32位整型Linux系统的值,用2的补码表示。注意,没有列出无符号数据类型的最小值,这些值应该都为0。在64位系统中,其long整型的最大值与表中long long整型的最大值相匹配。

img

<limits.h>中定义的整型值大小

函数sysconf、pathconf和fpathconf

运行时限制可调用下面3个函数之一获得。

1
2
3
4
5
#include <unistd.h>
long sysconf(int name);
long pathconf(const char *pathname, int name);
long fpathconf(int fd, int name);
// 所有函数返回值:若成功,返回相应值;若出错,返回-1

后面两个函数的差别是:一个用路径名作为其参数,另一个则取文件描述符作为参数。


基本系统数据类型

头文件<sys/types.h>中定义了某些与实现有关的数据类型,它们被称为基本系统数据类型(primitive system data type)。还有很多这种数据类型定义在其他头文件中。在头文件中,这些数据类型都是用C的typedef来定义的。它们绝大多数都以_t结尾。

img

一些常用的基本系统数据类型


习题

2.1 一些基本系统数据类型可以在多个头文件中定义。例如,在FreeBSD 8.0中, size_t在29个不同的头文件中都有定义。由于一个程序可能包含这29个不同的头文件,但是ISO C却不允许对同一个名字进行多次typedef,那么如何编写这些头文件呢?

2.1 下面是FreeBSD中使用的技术。在头文件<machine/_types.h>中定义可在多个头文件中出现的基本数据类型。例如:

1
2
3
4
5
6
7
8
9
10
typedef int      __int32_t;
typedef unsigned int __uint32_t;

#ifndef _MACHINE__TYPES_H_
...
#define _MACHINE__TYPES_H_
...
typedef __uint32_t  __size_t;
...
#endif /* _MACHINE__TYPES_H_ */

在每个可以定义基本数据类型size_t的头文件中,包含下面的语句序列。

1
2
3
4
#ifndef _SIZE_T_DECLARED
typedef __size_t   size_t;
#define _SIZE_T_DECLARED
#endif

这样,实际上只执行一次size_t的typedef。