UP | HOME

Unix标准和实现

Table of Contents

标准

ANSI C

1989年后期,C程序设计语言的ANSI标准X3.159-1989得到批准

此标准已被采用为国际标准 ISO/IEC 9899:1990

ANSI是美国国家标准学会,它是由制造商和用户组成的非赢利性组织

ANSI C标准的意图是 提供C程序的可移植性,使其能适合于大量不同的操作系统 ,而不只是UNIX。此标准不仅定义了C程序设计语言的 语法语义 ,也定义了其 标准库

     内核本身通常没有C库函数接口,如Linux的内核

IEEE POSIX

POSIX 的目的是 标准化各类Unix系统接口 ,以提高它们的应用程序在源代码级上的可移植性

POSIX定义了遵循它的操作系统必需提供的操作系统服务接口,而不是实现

所以并不区分系统调用和库函数。所有在标准中的例程都被称为函数

POSIX.1 本身没有专门定义超级用户的概念,但对一些操作要求区分操作权限

SUS和X/Open

由UNIX®商标的拥有者Open Group发布,是POSIX.1 的一个扩展超集,Open Group的前身即为X/Open;

SUS的全集称为XSI,一个Unix­like系统在拿到UNIX®商标之前,需要保证遵循XSI并服从SUS的强制要求

SUS的最新标准为SUS v3,发布于2004年,并经过了ISO的标准化。主要内容分为4个部分:

  • 基本定义
  • 系统接口
  • Shell和实用程序
  • 基本理论

FIPS

联邦信息处理标准,实际上它只是一个更加严格的POSIX.1标准

实现

各种不同Unix的实现都宣称依从POSIX,但又各自实现了自己的特性

  • SVR4
  • 4.3+BSD
  • Linux
  • FreeBSD

限制

  • 编译选择项:比如该系统是否支持 作业控制
  • 编译限制:比如 短整型的最大值 是什么
  • 运行限制:比如 文件名的最大字符数 为多少
    编译选择项和限制可在头文件中定义

    而运行时间限制要求进程调用函数去获得限制的常量值

    此外和文件系统有关的限制,比如文件名的最大字符数又和具体文件系统有关

事实上可以分成以下三类

  1. 编辑选择项及限制(头文件)
  2. 不与文件或目录相关联的运行限制
  3. 与文件或目录相关联的运行限制

ANSI C限制

所有由ANSI C定义的限制都是 编译限制

  • limit.h:基本数据类型的长度限制
  • float.h:浮点数类型的长度限制
  • stdio.h: FOPEN_MAX指的是同时打开的标准IO的最大个数,TMP_MAX临时文件名的最大字符长度

POSIX

POSIX.1定义了很多涉及 操作系统实现限制 的常数。主要分为以下几类

  • 固定的最小值,如LOGIN_NAME_MAX等
  • 固定值,SSIZE_MAX
  • 在运行时可增加的值。如RE_DUP_MAX等
  • 运行时固定值,如ARG_MAX(最大函数参数长度)等
  • 路径名不定值,如PATH_MAX 等

POSIX定义的值往往比实现要小,所以实际这些常量值需要通过 sysconf , pathconf , fpathconf 等函数获取

XSI

XSI也定义几个限制常量,这些常量大部分和 消息 相关,全部都被包含在 limit.h

不确定的运行时限制

最大路径名字 _PC_PATH_MAX 与最大打开文件数 _PC_OPEN_MAX

PATH_MAX在SUS v3 之前对是否包括了路径名称末尾的 null 字符('\0')没有明确定义

为保持兼容性,通常需要考虑此字符作为路径名字的一部分

动态获取限量值

#include <unistd.h>

//所有函数返回:若成功为相应常量的限制值,若出错为-1
//name: 常量名 以_SC_开头的常量名适用于sysconf, 相对的以_PC_开头的适用于pathconf和fpathconf
long sysconf(int name);
//pathname: 文件名
long pathconf(const char *pathname, int name);
//fileds: 文件描述符
long fpathconf(int filedes, int name);
  • sysconf:获取 系统在运行时的资源限制 ,如_SC_OPEN_MAX(限制一个进程可以打开文件的最大数量)等
  • pathconf:通过 路径名获取对应限制名称name的限制值
  • fpathconf:则通过 打开的文件描述符

返回值

其中有些限制名称只在某些特殊文件里有定义,如_PC_FILESIZEBITS只能用在目录中。文件限制通常直接跟文件系统的实现相关

  • 如果 name不是标准中定义的常量 的话,上述函数将返回 -1 ,并置errno为 EINVAL
  • 若为运行时不确定值,则只返回 -1
  • 函数调用成功时返回其限制值

功能测试宏

资源限制通常是与具体的系统实现相关的,为了保证可移植性,应 定义功能测试宏 强制程序运行时的限制符合标准

系统标准测试宏

功能测试宏包括了两个常量:

  • _POSIX_C_SOURCE
  • _XOPEN_SOURCE
#define _POSIX_C_SOURCE 200112L
#define _XOPEN_SOURCE 600

如果在C程序源文件中定义了这两个宏,则告诉编译器, 资源限制使用POSIX及SUS的定义,而不使用当前系统具体实现中的定义

C语言标准测试宏

__STDC__ 由符合ANSIC标准的编译程序自动定义。这样就允许编写ANSI C编译程序和非ANSI C编译器都能编译的程序

# ifdef __STDC__
void *myfunc(const char *, int);
# else
void *myfunc();
# endif

基本系统数据类型

基本系统数据类型包括 size_ttime_tuid_toff_tpthread_t 等。这些数据类型是不透明的,在各个具体的系统实现中通常由C的 typedef 语句重定义的,其原型可能是某种整型数也可能是个struct结构或者其他

Table 1: 基本系统数据类型
类型 说明
caddr_t 内存地址
clock_t 时钟滴答计数器(进程时间)
comp_t 压缩的时钟滴答
dev_t 设备号(主和次)
fd_set 文件描述符集
fpos_t 文件位置
gid_t 数值 组ID
ino_t i节点编号
mode_t 文件类型,文件创建方式
n1ink_t 目录项的连接计数
off_t 文件长度和位移量(带符号的)
pid_t 进程ID和进程组ID(带符号的)
ptrdiff_t 两个指针相减的结果(带符号的)
r1im_t 资源限制
sig_atomic_t 能原子地存取的数据类型
sigset_t 信号集
size_t 对象(例如字符串)长度(不带符号的)
ssize_t 返回字节计数的函数(带符号的)
time_t 日历时间的秒计数器
uid_t 数值 用户ID
wchar_t 能表示所有不同的字符码

为了考虑程序的可移植性, 不应直接使用其对应的C基本数据类型,而应该使用这些类型

Next:文件I/O

Previous:基础知识

Home:目录