UNIX 环境高级编程|UNIX 标准及实现
GitHub: https://github.com/storagezhang
Emai: debugzhang@163.com
本文为《UNIX 环境高级编程》第 2 章学习笔记
本章对 UNIX 环境编程的 3 个主要标准进行了说明:
- ISO C
 - POSIX
 - Single UNIX Specification
 
分析了这些标准对本书主要关注的 4 个实现所产生的影响:
- FreeBSD
 - Linux
 - Mac OS X
 - Solaris
 
这些标准都试图定义一些可能随实现而更改的参数,但是这些限制并不完美。
2.2 UNIX 标准化
ISO C
ISO C 标准的意图是提供 C 程序的可移植性,使其能适合于大量的不同的操作系统,而不只是适合 UNIX 系统。
- 此标准不仅定义了 C 程序设计语言的语法和语义,还定义了标准库。
 - 因为所有现金的 UNIX 系统都提供 C 标准中定义的库函数,所以该标准库非常重要。
 
| 头文件 | 说明 | 
|---|---|
| <asert.h> | 验证程序断言 | 
| <complex.h> | 复数算术运算支持 | 
| <ctype.h> | 字符分类和映射支持 | 
| <errno.h> | 出错码 | 
| <fenv.h> | 浮点环境 | 
| <float.h> | 浮点常量及特性 | 
| <inttypes.h> | 整型格式变换 | 
| <iso646.h> | 赋值、关系及一元操作符宏 | 
| <limits.h> | 实现常量 | 
| <locale.h> | 本地化类别及相关定义 | 
| <math.h> | 数学函数、类型声明及常量 | 
| <setjmp.h> | 非局部 goto | 
| <signal.h> | 信号 | 
| <stdarg.h> | 可变长度参数表 | 
| <stdbool.h> | 布尔类型和值 | 
| <stddef.h> | 标准定义 | 
| <stdint.h> | 整型 | 
| <stdio.h> | 标准 I/O 库 | 
| <stdlib.h> | 实用函数 | 
| <string.h> | 字符串操作 | 
| <tgmath.h> | 通用类型数学宏 | 
| <time.h> | 时间和日期 | 
| <wchar.h> | 扩充的多字节和宽字符支持 | 
| <wctype.h> | 宽字符分类和映射支持 | 
IEEE POSIX
POSIX 指的是可移植操作系统接口。
- 该标准的目的是提升应用程序在各种 UNIX 系统环境之间的可移植性。它定义了“符合 POSIX 的” 操作系统必须提供的各种服务。
 - POSIX 1003.1 说明了一个接口而不是一种实现,所以并不区分系统调用和库函数,所有在标准中的例程都被称为函数。
 - 该标准包含了 ISO C 标准库函数。
 - POSIX.1 没有包括超级用户的这样的概念,代之以规定某些操作要求“适当的优先权”。
 
Single UNIX Specification
Single UNIX Specification 是 POSIX.1 标准的一个超集,它定义了一些附加接口扩展了 POSIX.1 规范提供的功能。
2.3 UNIX 系统实现
标准只是接口的规范,这些标准由厂商采用,然后转变成具体实现。
目前 UNIX 主要有以下实现:
- SVR4
 - 4.4BSD
 - FreeBSD
 - Linux
 - Mac OS X
 - Solaris
 
2.5 限制
UNIX 系统实现定义了很多幻数和常量,其中有很多已被硬编码到程序中,或用特定的技术确定。
以下两种类型的限制是必需的:
- 编译时限制(短整型的最大值是什么?) 
   
- 编译时限制可在头文件中定义,程序在编译时可以包含这些头文件。
 
 - 运行时限制(文件名有多少个字符?) 
   
- 运行时现状要求进程调用一个函数获得限制值。
 
 
某些限制在一个给定的实现中可能是固定的(因此可以静态地在一个头文件中定义),而在另一个实现中则可能是变动的(需要有一个运行时函数调用),这种类型限制的一个例子是文件名的最大字符数。
为了解决这类问题,提供了以下 3 种限制:
- 编译时限制(头文件)
 - 与文件或目录无关的运行时限制(
sysconf函数) - 与文件或目录有关的运行时限制(
oathconf和fpathconf函数) 
ISO C 限制
ISO C 定义的所有编译时限制都列在头文件 <limits.h> 中,这些限制常量在一个给定系统中并不会改变。
<stdio.h> 头文件还定义了 3 个编译时限制:
FOPEN_MAX- 保证可同时打开的标准 I/O 流的最小个数,其最小值是 8.
 
TMP_MAX- 由 
tmpnam函数产生的唯一文件名的最大个数。 
- 由 
 FILENAME_MAX- 避免使用该常量
 - POSIX.1 提供了更好的替代常量(
NAME_MAX和PATH_MAX) 
POSIX 限制
POSIX.1 定义了很多涉及操作系统实现限制的常量,这些限制和常量分成下列 7 类:
- 数值限制
 - 最小值
 - 最大值
 - 运行时可以增加的值
 - 运行时不变值(可能不确定)
 - 其他不变值
 - 路径名可变值
 
在这些限制和常量中,某些可能定义在 <limits.h> 中,其余的按具体条件可定义、可不定义。
- 一个给定进程的实际值可能依赖于系统的存储总量。
 
这些最小值是不变的,不随系统而改变,它们指定了这些特征最具约束性的值。
 函数 sysconf、pathconf 和 fpathconf
 
 运行时限制可调用下面 3 个函数之一获得:
#include <unistd.h>
long sysconf(int name);
long pathconf(const char *pathname, int name);
long fpathconf(int fd, int name);
 
 参数:
name用于标识系统限制- 以 
_SC_开始的常量用作标识运行时限制的sysconf函数所使用的name参数 - 以 
_PC_开始的常量用作标识运行时限制的 ``pathconf和fpathconf函数所使用的name` 参数 
- 以 
 pathname:路径名fd:文件描述符
返回值:
-  
若成功,返回相应值
 -  
若出错,返回 -1
- 如果 
name参数并不是一个合适的常量,还要把errno置为EINVAL。 - 有些 
name会返回一个不确定的值,不确定的值通过返回 -1 来体现,而不改变errno的值。 
 - 如果 
 
守护进程
守护进程(daemon process)是指在后台运行且不与终端相连接的一种进程。
2.6 选项
如果我们要编写可移植的应用程序,而这些程序可能会依赖于这些可选的支持的功能,那么就需要一种可移植的方法来判断是否支持一个给定的选项。
POSIX.1 定义了 3 种处理选项的方法:
- 编译时选项定义在 <unistd.h> 中
 - 与文件或目录无关的运行时选项用 
sysconf函数来判断 - 与文件或目录有关的运行时选项通过调用 
pathconf或fpathconf函数来判断 
如果符号常量未定义,则必须使用 sysconf 、pathconf 或 fpathconf 来判断是否支持该选项:
name参数前缀_POSIX必须替换为_SC或_PC- 对于以 
_XOPEN为前缀的常量,在构成name参数时必须在其前放置_SC或_PC 
对于每一个选项,有以下 3 种可能的平台支持状态;
- 如果符号常量没有定义或者定义值为 -1,那么该平台在编译时并不支持相应选项。
 - 如果符号常量的定义值大于 0,那么该平台支持相应选项。
 - 如果符号常量的定义值为 0,则必须调用 
sysconf、pathconf或fpathconf来判断相应选项是否受到支持。 
2.8 基本系统数据类型
头文件 <sys/types.h> 中定义了某些与实现有关的数据类型,它们被称为基本系统数据类型。在头文件中,这些数据类型都是用 C 的 typedef 来定义的,它们绝大多数都以 _t 结尾。用这种方式定义了这些数据类型后,就不再需要考虑因系统不同而变化的程序实现细节。
| 类型 | 说明 | 
|---|---|
| clock_t | 时钟滴答计数器(进程时间) | 
| comp_t | 压缩的时钟滴答(POSIX.1 未定义) | 
| dev_t | 设备号(主和次) | 
| fd_set | 文件描述符集 | 
| fpos_t | 文件位置 | 
| gid_t | 数值组 ID | 
| ino_t | i 节点编号 | 
| mode_t | 文件类型,文件创建模式 | 
| nlink_t | 目录项的链接计数 | 
| off_t | 文件长度和偏移量(带符号的,如 lseek) |  
   
| pid_t | 进程 ID 和进程组 ID(带符号的) | 
| pthread_t | 线程 ID | 
| ptrdiff_t | 两个指针相减的结果(带符号的) | 
| rlim_t | 资源限制 | 
| sig_atomic_t | 能原子性地访问的数据类型 | 
| sigset_t | 信号集 | 
| size_t | 对象(如字符串)长度(不带符号的) | 
| ssize_t | 返回字节计数的函数(带符号的,如 read、write) |  
   
| time_t | 日历时间的秒计数器 | 
| uid_t | 数值用户 ID | 
| wchar_t | 能表示所有不同的字符码 | 
- 点赞
 - 收藏
 - 关注作者
 
            
           
评论(0)