第二章 UNIX标准及实现
一:主要内容:
本章主要讲述了UNIX系统在标准化的过程中的思考以及遇到的问题和一些限制。
二:UNIX标准化
在做UNIX标准化的过程中有很多组织参与到这里,制定了很多标准,如ISO C,IEEE POSIX,Single UNIX Specification等,这些标准主要制定是标准的C头文件都该有哪些,例如IEEE POSIX制定的标准C头文件就要比ISO C多一些,见下图:
值得注意的是ISO C只是定义了C标准函数库的函数原型、函数功能,而并未定义函数的具体实现。
同样的,POSIX也只是定义接口,而不定义具体的实现。 但是POSIX定义的头文件要多一些,包含非必要的总共有八十多个。
Single UNIX Specification标准的第一个版本由X/Open于1994年发布,此后经过多次更新,于2010年由Open Group发布第四个版本(SUSv4)。其中,Open Group是由两个工业社团——X/Open和Open Software Foundation (OSF)于1996年合并而构成的。
特别地,所有UNIX系统都是遵循XSI的实现。XSI除描述了一些可选的POSIX.1接口外,还定义了遵循XSI的实现所必须支持的可选POSIX.1接口。这些必须被支持的接口包括file synchronization、thread stack address and size attributes、thread process-shared synchronization和 the _XOPEN_UNIX symbolic constant。
三:UNIX系统的实现
书中作者说了很多UNIX系统,这里我们只说一下APUE这本书用到的测试系统。
本书用到的四种操作系统中包括:FreeBSD、Linux(这个大家应该都不陌生)、Mac OS X、Solaris。
四:限制
提到幻数大家都不陌生,同样的,UNIX系统实现时定义了很多幻数和常量,而且有很多甚至已经被硬编码到程序中去,由于大量标准化的努力,已经有若干种可以指的方法用以确定这些幻数和具体实现定义的限制。
其中有两类限制是必需的:编译时的限制,运行时的限制。可以简单地理解为在编译时就已经确定的限制和在运行时才能确定的限制,比如说int型的最大值是多少,这个肯定在编译时就限制了;再比如读入的文件名有多少个字符,这个只能等运行时才知道了,那也只能在运行的时候才能限制。
为了解决这类问题,提供了三种限制:编译时限制(头文件);与文件和目录无关的运行时限制(sysconf函数);与文件和目录有关的运行时的限制(pathconf和fpathconf)。
那么这里我们需要注意一点,如果一个特定的运行时限制不在头文件定态的定义,就必须调用三个conf函数中的一个来去确定其运行时的值。
下面是三个conf函数的函数定义和功能:
long sysconf(int name);
//取系统在运行时的资源限制,如_SC_OPEN_MAX(限制一个进程可以打开文件的最大数量)等;(name的取值见书P33,表2-10)
long pathconf(const char *pathname, int name);
//通过路径名获取对应限制名称 name 的限制值;(name的取值见书P34,表2-11)
long fpathconf(int filedes, int name);
//通过打开的文件描述符获取对应限制名称 name 的限制值,其中有些限制名称只在某些特殊文件里有定义,如_PC_FILESIZEBITS 只能用在目录中。文件限制通常直接跟文件系统的实现相关;(name的取值见书P34,表2-11)
五:不确定的运行时限制
正常来说一个限制值没有在头文件中定义,那么编译时也就不能使用,但是又两种特殊情况,它们的值是不确定的,所以在运行的时候值也是未知的,那就是为一个路径名分配存储去和确定文件描述符的数目。
在POSIX.1中试图用PATH_MAX来帮助我们确定路径名的存储区大小,用OPEN_MAX来确定最大打开文件数的大小,但是如果这两个值是不确定的,那么在运行的时候出问题也是显而易见的。
六:选项
选项有点类似于限制,对他的处理方法也是三种:编译时选项定义在<unistd.h>中;与文件和目录无关的运行时限制通过sysconf函数来判断;与文件和目录有关的运行时的限制通过pathconf和fpathconf来判断。具体的选项值就不赘述了,有兴趣可以上网查一下。
七:功能测试宏
资源限制通常是与具体的系统实现相关的,为了保证可移植性,应定义功能测试宏强制程序运行时的限制符合标准。
功能测试宏包括了两个常量:_POSIX_C_SOURCE(POSIX 标准)与_XOPEN_SOURCE(SUS 标准)。
如果在 C 程序源文件中定义了这两个宏,则告诉编译器,资源限制使用 POSIX 及 SUS 的定义,而不使用当前系统具体实现中的定义。这两个宏应定义为一个值,如:
#define _POSIX_C_SOURCE 200112L //令源文件的系统限制遵循 POSIX.1 标准
#define _XOPEN_SOURCE 600 //令源文件的系统限制遵循 SUS v3 标准
也可以不定义在头文件中,而通过编译选项加入宏定义,对于 gcc(1)为D 选项。
八:基本系统数据类型
包括了 size_t、time_t、uid_t、off_t、pthread_t 等数据类型,它们是不透明的数据类型。在各个具体的系统实现中通常由 C 的 typedef 语句重定义的,其原型可能是某种整型数也可能是个 struct 结构或者其它。