[单刷APUE系列]第二章——Unix标准及实现

目录

[单刷APUE系列]第一章——Unix基础知识[1]
[单刷APUE系列]第一章——Unix基础知识[2]
[单刷APUE系列]第二章——Unix标准及实现
[单刷APUE系列]第三章——文件I/O
[单刷APUE系列]第四章——文件和目录[1]
[单刷APUE系列]第四章——文件和目录[2]
[单刷APUE系列]第五章——标准I/O库
[单刷APUE系列]第六章——系统数据文件和信息
[单刷APUE系列]第七章——进程环境
[单刷APUE系列]第八章——进程控制[1]
[单刷APUE系列]第八章——进程控制[2]
[单刷APUE系列]第九章——进程关系
[单刷APUE系列]第十章——信号[1]

Unix标准化

Unix编程环境和C程序设计语言是如此的普遍,而且标准化工作做了非常多,但是20世纪80年代Unix版本种类的剧增以及他们差别的扩大导致跨平台移植变得越来越难,很多用户都呼吁对其进行标准化。
Unix标准化有四个,ISO C、IEEE POSIX、Single Unix Specification、FIPS

ISO C

ISO C标准现在由ISO/IEC的C程序设计语言国际标准工作组维护和开发。ISO C标准的意图是提供C程序的可移植性,使其能适应于大量的操作系统。标准不但定义了C程序设计语言的语法,还规定了必备的标准库。
1989年,C程序设计语言的ANSI标准被采纳为国际标准,也是最早的一次标准化过程,目前被称为C89标准
1999年,ISO C标准被更新,在C89的基础上增加了基本数据类型、关键字和一些系统函数,这也是目前主流的C语言编译器标准,即C99标准,是继C89以后的第二个C语言官方标准。自1999年以来,也有3次技术勘误用于修正ISO C标准,分别于2001年、2004年和2007年,2011年还更新了C11标准,但是非常遗憾的是,标准审批和实际生产还是有一定时间延迟,所以C11标准目前还并非主流。
根据ISO C标准,C程序设计语言有24个头文件,目前所有的Unix环境都支持这些头文件。

头文件 说明
验证程序断言
复数运算支持
字符分类和映射支持
错误码
浮点环境
浮点支持
整型格式转换
赋值、关系、一元操作符宏
实现常量
本地化支持
数学运算库
非局部goto
信号支持
可变长度参数
布尔类型支持
标准定义
标准整形
标准输入输出
实用函数库
字符串操作
通用类型数学宏
时间日期支持
多字节宽字符支持
宽字符分类和映射支持
IEEE POSIX

IEEE POSIX在原书内指的是IEEE 1003.1操作系统接口标准,该标准的1988版本递交给ISO,最终成为了国际标准POSIX.1,而后IEEE 1003.1工作组对其作出很多修订,包括了著名的pthreads多线程接口。POSIX标准不仅包含了ISO C标准函数库,还根据标准要求提供包含了系统调用和库函数的头文件,在这里就不一一列出了。由于POSIX标准只是定义了操作系统接口而非实现,所以并未区分系统调用和库函数。其接口分为两部分,一部分是强制规定必须的部分,而另外一部分是非强制要求的可选部分,

Single Unix Specification

Single Unix Specification是POSIX.1标准的一个超集,它定义了一系列附加接口扩展了POSIX.1的功能,Open Group拥有Unix商标,他们定义了SUS标准,一个系统想要称为Unix系统,就必须实现这些接口,并且通过验收性测试,才能得到Unix商标使用权,其中就包括了Mac OS X系统,而Linux虽然实现了这些接口,但是从未提出过申请,所以Linux没有得到过Unix商标。

FIPS

FIPS是联邦信息处理标准,实际上并没有什么卵用,只是美国政府采购的标准,后来还被撤回了。

限制

在做Unix环境开发时,我们经常遇到跨平台编译的问题,例如:x86_64和x86字长的不同导致的数据类型长度不一致。不同Unix版本对接口实现程度不一致。其中最重要的问题就是编译时限制和运行时限制。
编译时限制我们可以通过在头文件中进行宏定义,然后使用include指令包含这些头文件。也可以向编译器传入-Dmacroname=value传入宏定义参数来动态定义这些限制。
运行时限制则要求进程调用库函数来获得系统内置的参数。
Unix系统提供了一下两种限制:

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

  2. 运行时限制:sysconfpathconffpathconf

除了Unix系统要求的限制,C程序设计语言的ISO C标准也提供了编译时限制,所有的限制都被放在头文件中,但是注意,这些限制的具体值实际上是由Unix系统规定的而不是C语言规定。
例如头文件,开发者可以利用它提供的常量、宏和派生类型使其代码与显式指定大小的数据项兼容,而不管编译环境如何。众所周知,由于x86_64和x86之间的区别,整形类型所使用的内存空间是不同的,也就是说,我们很可能滥用整形导致边界溢出的问题,在实际开发中,推荐的方法是使用定长的整形,而不是int和long,而这个文件也包含了格式化字符串所需要的描述参数的宏定义,极大地方便了开发者的使用。
Unix系统标准规定的所有限制只包含两种:POSIX限制和XSI限制,对于开发者来说,这两种限制没有任何区别,都是以同样的方式可以获取。
正如前文所言,限制分为编译时限制和运行时限制,运行时限制可以通过下列三个函数获取

long sysconf(int name);
long pathconf(const char *pathname, int name);
long fpathconf(int fd, int name);

顺便更正一下原著关于fpathconf函数返回值的错误,原著是log,实际上是long。

The pathconf() and fpathconf() functions provides a method for applications to determine the current value of a configurable system limit or option variable associated with a pathname or file descriptor.

非常简单易懂,这两个函数实际上没什么区别,只是用文件描述符来代替文件路径罢了。

     _PC_LINK_MAX
             The maximum file link count.

     _PC_MAX_CANON
             The maximum number of bytes in terminal canonical input line.

     _PC_MAX_INPUT
             The minimum maximum number of bytes for which space is available in a terminal input queue.

     _PC_NAME_MAX
             The maximum number of bytes in a file name.

     _PC_PATH_MAX
             The maximum number of bytes in a pathname.

     _PC_PIPE_BUF
             The maximum number of bytes which will be written atomically to a pipe.

     _PC_CHOWN_RESTRICTED
             Return 1 if appropriate privileges are required for the chown(2) system call, otherwise 0.

     _PC_NO_TRUNC
             Return 1 if file names longer than KERN_NAME_MAX are truncated.

     _PC_VDISABLE
             Returns the terminal character disabling value.

     _PC_XATTR_SIZE_BITS
             Returns the number of bits used to store maximum extended attribute size in bytes.  For example, if the maximum attribute size
             supported by a file system is 128K, the value returned will be 18.  However a value 18 can mean that the maximum attribute size
             can be anywhere from (256KB - 1) to 128KB.  As a special case, the resource fork can have much larger size, and some file system
             specific extended attributes can have smaller and preset size; for example, Finder Info is always 32 bytes.

上面就是pathconf函数族可能获取的值,具体的可以参考

     _SC_ARG_MAX
             The maximum bytes of argument to execve(2).

     _SC_CHILD_MAX
             The maximum number of simultaneous processes per user id.

     _SC_CLK_TCK
             The frequency of the statistics clock in ticks per second.

     _SC_IOV_MAX
             The maximum number of elements in the I/O vector used by readv(2), writev(2), recvmsg(2), and sendmsg(2).

     _SC_NGROUPS_MAX
             The maximum number of supplemental groups.

     _SC_NPROCESSORS_CONF
             The number of processors configured.

     _SC_NPROCESSORS_ONLN
             The number of processors currently online.

     _SC_OPEN_MAX
             The maximum number of open files per user id.

     _SC_PAGESIZE
             The size of a system page in bytes.

     _SC_STREAM_MAX
             The minimum maximum number of streams that a process may have open at any one time.

     _SC_TZNAME_MAX
             The minimum maximum number of types supported for the name of a timezone.

     _SC_JOB_CONTROL
             Return 1 if job control is available on this system, otherwise -1.

     _SC_SAVED_IDS
             Returns 1 if saved set-group and saved set-user ID is available, otherwise -1.

     _SC_VERSION
             The version of IEEE Std 1003.1 (``POSIX.1'') with which the system attempts to comply.

     _SC_BC_BASE_MAX
             The maximum ibase/obase values in the bc(1) utility.

     _SC_BC_DIM_MAX
             The maximum array size in the bc(1) utility.

     _SC_BC_SCALE_MAX
             The maximum scale value in the bc(1) utility.

     _SC_BC_STRING_MAX
             The maximum string length in the bc(1) utility.

     _SC_COLL_WEIGHTS_MAX
             The maximum number of weights that can be assigned to any entry of the LC_COLLATE order keyword in the locale definition file.

     _SC_EXPR_NEST_MAX
             The maximum number of expressions that can be nested within parenthesis by the expr(1) utility.

     _SC_LINE_MAX
             The maximum length in bytes of a text-processing utility's input line.

     _SC_RE_DUP_MAX
             The maximum number of repeated occurrences of a regular expression permitted when using interval notation.

     _SC_2_VERSION
             The version of IEEE Std 1003.2 (``POSIX.2'') with which the system attempts to comply.

     _SC_2_C_BIND
             Return 1 if the system's C-language development facilities support the C-Language Bindings Option, otherwise -1.

     _SC_2_C_DEV
             Return 1 if the system supports the C-Language Development Utilities Option, otherwise -1.

     _SC_2_CHAR_TERM
             Return 1 if the system supports at least one terminal type capable of all operations described in IEEE Std 1003.2 (``POSIX.2''),
             otherwise -1.

     _SC_2_FORT_DEV
             Return 1 if the system supports the FORTRAN Development Utilities Option, otherwise -1.

     _SC_2_FORT_RUN
             Return 1 if the system supports the FORTRAN Runtime Utilities Option, otherwise -1.

     _SC_2_LOCALEDEF
             Return 1 if the system supports the creation of locales, otherwise -1.

     _SC_2_SW_DEV
             Return 1 if the system supports the Software Development Utilities Option, otherwise -1.

     _SC_2_UPE
             Return 1 if the system supports the User Portability Utilities Option, otherwise -1.

常用的就是这些,另外可能还有一些非标准参数,这里就不在叙述。想必大家也看出来了,以_SC_开头的就是sysconf,以_PC_开头的就是pathconf
关于原著中不确定的运行时限制,原文写的非常啰嗦,实际上没有什么卵用,因为虽然POSIX规定了很多限制,但是很多都没有被实际实现,所以碰到这种情况,只能使用条件编译、循环尝试、错误码判断等hack手段来搞定。

功能测试宏

由于Unix版本众多,各自的实现也不同,几乎每个Unix实现都自带了自定义的功能选项,为了保证只使用POSIX标准规范定义,我们可以使用_POSIX_C_SOURCE宏定义和_XOPEN_SOURCE宏定义,这也被称为功能测试宏。我们可以给C编译器传入-Dmacroname=value的形式,也可以在头文件中设置宏定义。

基本系统数据类型

为了保证跨平台开发使用同样的类型,Unix标准要求系统提供基本数据类型以供开发者使用,这些数据类型都已_t结尾,根据系统字长和平台的不同,他们具体的实现空间也不同,但是至少保证了不会因为系统不同而去关注具体实现细节。

你可能感兴趣的:(c,unix,apue)