一、UNIX标准化:

1.ISO C

ISO C (ISO是国际标准化组织)是C程序设计语言的标准,适用于一切使用C语言编程的场合

主要有两个版本的国际C标准:

一个是C89,即ANSI C(ANSI是美国国家标准学会),这是通行的实际标准;

另一个是C99,主要是在兼容C89的基础进行了扩充,如增加了restrict(强制所修饰类型只能为指针的修饰符)关键字等。

2.IEEE POSIX

IEEE是:电气与电子工程师协会,POSIX是可移植的操作系统接口,POSIX由IEEE制定,通过ISO进行标准化。

该标准的目的是提高应用程序在各种UNIX系统环境之间的可移植性。

当前通行的标准为POSIX.1,其包含了 ISO C 标准库函数。

3.Single UNIX Specification

Single UNIX Specification(单一UNIX规范)是POSIX.1标准的一个超集,.定义了一些附加接口。

这些接口扩展了基本的POSIX.1规范所提供的功能,相应的接口系统全集被称为X/Open系统接口。

二、UNIX系统实现

1.SVR4(UNIX系统V第4版):是AT&T的UNIX系统实验室的产品

2.4.4BDS:此版是由加州大学伯克利分校的计算机系统研究组研究开发和分发的。

3.FreeBDS:其基础是4.4BSD-Lite操作系统

4.Linux:是在POSIX标准指导下发布的独立UNIX分支,使用GPL许可证。

5.Mac OS X:Mac OS X内核称为Darwin,在Mach微内核和FreeBSD的基础上开发,主要运行于苹果计算机的PowerPC处理器。

6.Solaris:由Sun公司开发的UNIX系统版本,基于SVR4.

7.其他UNIX系统

三、限制

1.ISO C 限制

ISO C限制和常量被分为5类:

a.不变的最小值

在<limits.h>里定义的POSIX.1的不变最小值
名称 描述:...的可接受的最小值
_POSIX_ARG_MAX exec函数参数的长度 4,096
_POSIX_CHILD_MAX 每个真实用户ID的子进程数 25
_POSIX_HOST_NAME_MAX gethostname返回的主机名的最大长度 255
_POSIX_LINK_MAX 一个文件的链接数 8
_POSIX_LOGIN_NAME_MAX 登录名的最大长度 9
_POSIX_MAX_CANON 终端最简洁的(canonical)输入队列的字节数 255
_POSIX_MAX_INPUT 终端输入队列的可用空格 255
_POSIX_NAME_MAX 文件名的字节数,不包括终止字符null 14
_POSIX_NGROUPS_MAX 一个进程的同步的补充组ID的数量 8
_POSIX_OPEN_MAX 一个进程打开的文件数 20
_POSIX_PATH_MAX 路径名的字节数,包括终止符null 256
_POSIX_PIP_BUF 可被原子写入管道的字节数 512
_POSIX_RE_DUP_MAX 当使用间隔标记“\{m,n\}”时,被regexec和regcomp函数认可的基本正则表达式的重复出现次数 255
_POSIX_SSIZE_MAX 可以存入ssize_t对象的值 32,767
_POSIX_STREAM_MAX 一个进程能同时打开的标准I/O流的数量 8
_POSIX_SYMLINK_MAX 符号链接的字节数 255
_POSIX_SYMLOOP_MAX 路径名解析时可以转换的符号链接数 8
_POSIX_TTY_NAME_MAX 终端设备名的长度,包括终止符null 9
_POSIX_TZNAME_MAX 时区名的字节数 6

b.不变值:SSIZE_MAX

c.运行期可增长的值:CHARCLASS_NAME_MAX、COLL_WEIGHTS_MAX、LINE_MAX、NGROUPS_MAX、RE_DUP_MAX;

d.运行期可变化的值(可能不定):ARG_MAX、CHILD_MAX、HOST_NAME_MAX、LOGIN_NAME_MAX、OPEN_MAX、PAGESIZE、RE_DUP_MAX、STREAM_MAXS、 SYMLOOP_MAX、TTY_NAME_MAX和TZNAME_MAX;

e.路径名变量的值(可能不定):FILESIZEBITS、LINK_MAX、MAX_CANON、MAX_INPUT、NAME_MAX、PATH_MAX、PIPE_BUF和SYMLINK_MAX。

在这44个限量和常量中,有些可能定义在<limits.h>里,而其它的可能有也可能没有定义,取决于特定的条件 。

2.XSI限制

XSI同样定义了处理实现限量的常数,包括:

a.不变最小量:下表中的10个常量;

b.数字限量:LONG_BIT和WORD_BIT;

c.运行期不变值,可能不确定:ATEXIT_MAX、IOV_MAX和PAGE_SIZE。

<limits.h>里定义的XSI不变最小值
名称
描述
最小可接受值
典型值
NL_ARGMAX printf和scanf调用数字的最大值 9 9
NL_LANGMAX LANG环境变量的最大字节数 14 14
NL_MSGMAX 最大消息数量 32,767 32,767
NL_NMAX 多对一映射字符的最大字节数 未定义 1
NL_SETMAX 最大集合数量 255 255
NL_TEXTMAX 消息字符串的最大字节数 _POSIX2_LINE_MAX 2,048
NZERO 默认的进程优先级 20 20
_XOPEN_IOV_MAX readv和writev使用的iovec结构的最大数量 16 16
_XOPEN_NAME_MAX 文件名的最大字节数 255 255
_XOPEN_PATH_MAX 路径名的最大字节数 1,024 1,024

上表中有许多值是用来处理消息类别。最后两个值证明了POSIX.1的最小值太小了,很可能只允许嵌入式的POSIX.1系统,所以单一UNIX规范在XSI标准里加入更大的最小值。

3.函数synconf、pathconf和fpathconf

我们已经列出一个系统实现必须支持的各种最小值,但是我们怎么知道一个特定系统真正支持了那些限量呢?如我们早先所述,这些限量中有些可以在编译期可用,而一些只有在运行期得到。我们也提到过有些限量在某个系统上是固定的,而其它可能是变化的,因为它们与文件或目录相关。运行期限量可以通过调用以下三个函数来得到:

#include <unistd.h>
long sysconf(int name);
long pathconf(const char* pathname, int name);
long fpathconf(int filedes, int name); 

这三个函数成功都返回一个相应的值,而失败则返回-1。

最后两个函数的区别在于一个接受路径名作为参数,而另一个接受文件描述符作为参数。

下表列出了sysconf得到系统限量所用的名字参数,都以_SC_开头:

sysconf的名字参数以及相应的限量
限量名
描述
名字参数
AGR_MAX exec函数参数的最大长度,以字节为单位 _SC_ARG_MAX
ATEXIT_MAX 可以被atexit函数注册的函数的最大数量 _SC_ATEXIT_MAX
CHILD_MAX 一个真实用户ID可以拥有的最大进程数 _SC_CHILD_MAX
clock ticks/second 每秒钟的时钟周期 _SC_CLK_TCK
COLL_WEIGHTS_MAX 在本地定义文件里可以赋值给LC_COLLATE命令关键字的重量的最大数量 _SC_SOLL_WEIGHTS_MAX
HOST_NAME_MAX gethostname返回的主机名的最大长度 _SC_HOST_NAME_MAX
IOV_MAX readv和writev使用的iovec结构的最大数量 _SC_IOV_MAX
LINE_MAX 实用工具的输入行的最大长度 _SC_LINE_MAX
LOGIN_NAME_MAX 登录名的最大长度 _SC_LOGIN_NAME_MAX
NGROUPS_MAX 每个进程的同步补充组ID数 _SC_NGROUPS_MAX
OPEN_MAX 一个进程打开文件的最大数量 _SC_OPEN_MAX
PAGESIZE 系统内存页的字节数 _SC_PAGESIZE
PAGE_SIZE 系统内存页的字节数 _SC_PAGE_SIZE
RE_DUP_MAX regexec和regcomp函数使用间隔符\{m,n\}可以识别的基本表达式的重复次复 _SC_RE_DUP_MAX
STREAM_MAX 在任何时候一个进程的标准流的最大数量;如果有定义,这个值必须与FOPEN_MAX一样 _SC_STREAM_MAX
SYMLOOP_MAX 路径名解析时可以处理的符号链接数 _SC_SYMLOOP_MAX
TTY_NAME_MAX 终端设备名的长度,包括终止符null _SC_TTY_NAME_MAX
TZNAME_MAX 时区名的最大字节数 _SC_TZNAME_MAX

下表列出了pathconf和fpathconf函数使用的名字参数,都以_PC_开头:

pathconf和fpathconf的名字参数以及相应限量
限量名 描述 名字参数
FILESIZEBITS 为了表示在指定目录下允许的普通文件大小的最大值,所使用的有符号整型值所需的最小比特位数 _PC_FILESIZEBITS
LINK_MAX 一个文件链接数的最大值 _PC_LINK_MAX
MAX_CONON 一个终端最简洁的输入队列的最大字节数 _PC_MAX_CONON
MAX_INPUT 一个终端的输入队列可用空间的字节数 _PC_MAX_INPUT
NAME_MAX 文件名的最大字节数,不包括终止符null _PC_NAME_MAX
PATH_MAX 相对路径名的最大字节数,包括终止符null _PC_PATH_MAX
PIPE_BUF 可以原子写入管道的最大字节数 _PC_PIP_BUF
SYMLINK_MAX 一个符号链接的字节数 _PC_SYMLINK_MAX

下面再深入讨论下这三个函数的不同的返回值:

1、如果名字参数不正确,这三个函数都会返回-1并设置errno值为EINVAL。

2、一些名字参数可以返回一个变量的值,或者表明这个值是不确定的。通过返回-1但不改变erron的值来表示一个不确定的值;

3、_SC_CLK_TC的返回值是每秒钟的时钟周期,用来与times函数的返回值共同使用。

在传递路径名给pathconf和域参数给fpathconf时有些约束。如果这些约束中任意一个没有满足,则结果无定义:

1、_PC_MAX_CONON和_PC_MAX_INPUT的对应的文件并须是一个终端文件;

2、_PC_LINK_MAX的对应的文件既可以是文件也可以是目录。如果相应文件是一个目录,则返回值对应于目录本身,而不是目录下的文件;

3、_PC_FILESIZEBITS和_PC_NAME_MAX的相应文件必须是目录。返回值对应于这个目录下的文件;

4、_PC_PATH_MAX相应的文件必须是目录。当这个目录是工作目录时,返回值是相对路径名的最大长度。(不幸的是,这不是我们想知道的绝对路径的真实长度,稍后再来讨论这个问题。)

5、_PC_PIPE_BUF的相应文件必须是个管道,FIFO或者目录。前两种情况下返回值为相应管道或FIFO的限量。最后一种情况的返回值为指定目录下创建的任一FIFO的限量。

6、_PC_SYMLINK_MAX的相应文件必须是一个目录。返回值为目录里的符号链接可以包含的字符串的最大长度。

4.不确定的运行期限量(Indeterminate Runtime Limits)

我们之前提到了有运行期变量可以是不确定的。问题在于如果这些限量没有在<limits.h>里定义,那我们就不能在编译期使用它们。而且如果它们的值是不确定的,那么可能在运行期也没有定义!我们来看下两个特殊的情况:为路径名分配内存,以及决定文件描述符的数量。

路径名(Pathname)

许多程序需要为路径名分配内存。典型地,内存在编译期分配,而一些魔数(没有一个是正确的值)被用来作为数组尺寸:256、512、1024或都标准I/O常量BUFSIZ。定义在<sys/parm.h>里的4.3BSD常量MAXPATHLEN才是正确的值,但许多程序都不用它。

POSIX.1试图用PATH_MAX来解决这个问题,但如果这个值是不确定的,那我们仍然不走运。本文使用下面这个函数来动态地为路径名分配内存:

    #include <errno.h>#include <limits.h>#include <unistd.h>#ifdef PATH_MAXstatic int pathmax = PATH_MAX;#elsestatic int pathmax = 0;#endif#define SUSV3 200112Lstatic long posix_version = 0;/* If MATH_MAX is indeterminate, no guarantee this is adquate */#define PATH_MAX_GUESS 1024void err_sys(const char* msg);char *path_alloc(int *sizep) /* also return allocated size, if nonnull */{char *ptr;int size;if (posix_version == 0)posix_version = sysconf(_SC_VERSION);if (pathmax == 0) { /*first time through */errno = 0;if ((pathmax = pathconf("/", _PC_PATH_MAX)) < 0) {if (errno == 0)pathmax = PATH_MAX_GUESS; /* it's indeterminate */elseerr_sys("pathconf error for _PC_PATH_MAX");} else {pathmax++; /* add one since it's relative to root */}}if (posix_version < SUSV3)size = pathmax + 1;elsesize = pathmax;if ((ptr = malloc(size)) == NULL)printf("malloc error for pathname");if (sizep != NULL)*sizep = size;return(ptr);}void err_sys(const char* msg) {printf("%s\n", msg);exit(1);}

如果PATH_MAX在<limits.h>里定义了,那就使用它,不然就调用pathconf。如果第一个参数是工作路径,那么pathconf的返回值是一个相对路径名的最大尺寸,所以我们把根目录作为第一个参数,而后在结果上加1。如果pathconf指出PATH_MAX是不确定的,那我们只有猜测一个值了。

SUSv3之前的标准并没有清楚说明PATH_MAX最末尾是否包括一个null的字节。如果操作系统实现信赖于这些早期的标准,则我们需要加一个字节的内存,这样会更安全些。

处理不确定结果情况的正确方法取决于分配的空间怎样被使用。如果分配的内存是为了函数调用getcwd--比如:返回当前工作目录的绝对路径名--而且如果分配的空间太小的话,那errno会返回一个错误ERANGE。我们可以接着调用realloc来增加这块分配的空间并再次尝试。我们可以持续这样做,直到getcwd成功为止。

打开文件的最大数量(Maximum Number of Open Files)

一个后台进程(daemon process)(或守护进程、精灵进程):运行在后台,不与任何终端关联的进程。

一些程序用以下代码,设想常量NOFILE定义在<sys/param.h>头文件里:

#include <sys/param.h>
for (i = 0; i < NOFILE; i++)close(i);

其它一些程序使用一些版本的<stdio.h>提供的常量_NFILE作为上限。有些把它硬编码为20.

我们本希望用POSIX.1的值OPEN_MAX来决定这个值,但如果这个值是不确定的,我们仍然会有问题。如果我们把代码写成下面的模样,而同时OPEN_MAX是不确定的,那会造成死循环,因为sysconf会返回-1:

#include <unistd.h>
for (i = 0; i < sysconf(_SC_OPEN_MAX); i++)close(i);

我们最好的解决方案是仅仅关闭所有不超过一个任意上限(比如256)的描述符。和我们的pathname例子一样,这个并不保证可以在所有情况下都工作,但这是我们能做的最好的事情。看如下代码:

    #include <errno.h>#include <limits.h>#include <unistd.h>#ifdef OPEN_MAXstatic long openmax = OPEN_MAX;#elsestatic long openmax = 0;#endif/** If OPEN_MAX is indeterminate, we're not* guaranteed that this is adequate.*/#define OPEN_MAX_GUESS 256void err_sys(const char* msg);longopen_max(void){if (openmax == 0) { /* first time through */errno = 0;if ((openmax = sysconf(_SC_OPEN_MAX)) < 0) {if (errno == 0)openmax = OPEN_MAX_GUESS; /* it's indeterminate */elseerr_sys("sysconf error for _SC_OPEN_MAX");}}return(openmax);}

我们可能想尝试调用close函数,直到得到一个返回的错误,但是这个从close(EBADF)返回的错误并不能区分它是一个无效的文件描述符,还是这个文件描述符并没有打开。如果我们尝试使用这种技术,但描述符9并没有打开而描述符10被打开,我们可以终止在9而不能关闭10。如果OPEN_MAX溢出的话,dup函数确实返回一个特定的错误,但只能重复这个描述符两百多次才能得到这个值。

一些系统实现会返回LONG_MAX当作限值,来有效的表示没有限制。Linux的ATEXIT_MAX就是其一。这不是个好方法,因为它可能会导致程序很坏的行为。

比如,我们可以用Bourne-again shell的内置ulimit命令来改变我们进程可以同时打开的文件数的最大值。如果这个限制要设置成无限制的话,通常需要一个特殊(超级用户)的权限。但一旦它被设置为无限的话,sysconf会返回LONG_MAX作为OPEN_MAX的值。程序信赖于这个值作为关闭的文件描述符的上限,而尝试关闭2,147,483,647个文件描述符是非常浪费时间的,而它们之中大多数都没有被使用。

支持UNIX单一规范里的XSI扩展的系统会提供getrlimit函数。它能用来返回一个进程能打开的描述符的最大数量。利用这个函数,我们可以确保我们的进程没有打开超过预设的上限数的文件,从而避免上述问题。

OPEN_MAX被POSIX称为运行期不变量,意味着它的值不能在一个进程的生命周期内改变。但在支持XSI扩展的系统上我们可以调用setrlimit函数在为一个运行着的进程改变这个值。(这个值也可以在C shell上用limit命令改变,或在Bourne、Bourne-again和Knon shell上用ulimit函数。)如果我们的系统支持这个功能,我们可以改变上述代码:每次调用open_max函数时,都调用sysconf,而不仅仅在第一次调用时。

5.在Linux的shell下

若要知道系统当前都有哪些运行时限制,可以使用如下命令:

find /proc/sys -name *max*

此命令行可打印出当前运行的内核中各种资源限制的名称,可以直接用cat(1)等命令查看其内容。通常可以root权限修改,但一般通过使用命令ulimit(1)修改。

四、POSIX.1 选项

选项说明了系统具体实现的可选功能,包括。如JOB_CONTROL、THREADS、CHOWN_RESTRICTED等。

其值为负数时表示当前系统不支持这些可选功能,为正数时表示支持,为0时可用sysconf、pathconf、fpathconf等函数的返回值确定是否支持;

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

五、功能测试宏

功能测试宏包括了两个常量:_POSIX_C_SOURCE(POSIX标准)与_XOPEN_SOURCE(SUS标准)。如果在C程序源文件中定义了这两个宏,则告诉编译器,资源限制使用POSIX及SUS的定义,而不使用当前系统具体实现中的定义。这两个宏应定义为一个值,如:

#define _POSIX_C_SOURCE 200112L
#define _XOPEN_SOURCE 600

第一个使得源文件的系统限制遵循POSIX.1标准,第二个为SUS v3标准。也可以不定义在头文件中,而通过编译选项加入宏定义,对于gcc(1)为-D选项。

六、基本系统数据类型

包括了size_t、time_t、uid_t、off_t、pthread_t等数据类型,在各个具体的系统实现中通常由C的typedef语句重定义的,其原型可能是某种整型数也可能是个struct结构。使用这些数据类型而不直接用C中的int、long等基本数据类型也是为了考虑程序的可移植性。

UNIX标准化及实现相关推荐

  1. UNIX标准化及实现之UNIX标准化、UNIX系统实现、标准和实现的关系以及ISO C标准头文件...

    一.UNIX标准化 1.ISO C (International Organization for Standardization) 2.IEEE POSIX (Institue of Electri ...

  2. UNIX 标准化 --ISO C标准 IEEE POSIX 标准 Single Unix Specification(SUS)

    原文地址 为什么要进行标准化呢?  在早期,Unix应用程序虽然可以在不同版本的unix操作系统之间移植相当容易,但是随着Unix系统版本的剧增以及他们的差别越来越大,不同版本的unix系统的应用程序 ...

  3. UNIX标准化及实现之POSIX标准可选头文件

    POSIX标准定义的可选头文件 头文件 说明 <aio.h> 异步I/O <mqueue.h> 消息队列 <pthread.h> 线程 <sched.h> ...

  4. linux非标准头文件,Linux学习:unix的标准化的实现(Linux中各种限制-数据类型-各种标准化头文件介绍)...

    作为Linux的前身,unix标准化是十分重要的.我在这里挑几个重要的点说明. 1:Linux中各种限制.Linux中限制有编译时限制和运行时限制,另外有一些限制是由于我们的实现不同而不同,因此我们需 ...

  5. 《Unix环境高级编程》学习笔记:从点到面

    以前在课堂上学习过<Unix初级教程(第四版)>,对于Unix有了一点了解.由于以后使用的需要,要对它进行比较深入的学习,为此需要阅读不少的书籍,这本<Unix环境高级编程>便 ...

  6. UNIX环境高级编程(APUE)读书笔记

    未完待续 第一章 基础 1.1 引言 所有操作系统都为它们所运行的程序提供服务.典型服务包括:执行新程序.打开文件.写入/读取文件.分配存储区以及获得当前时间等. 1.2 UNIX体系结构 内核:从严 ...

  7. [阅读体会] UNIX环境高级编程

    文章目录 写在开始阅读前 (我会的知识点,在体会里是不提的,并不是书中没有,这里着重于记录我之前不会的,但读过书之后学会的.) 第一章 第二章 2.1 引言 2.2 UNIX标准化 2.2.1 ISO ...

  8. Unix环境高级编程 笔记

    Unix环境高级编程(第二版)学习笔记 这是一次较长时间的整理,然而跳跃了一些章节和很多知识点,仍然是很不完善很不全面的. 前言 操作系统某些问题 严格意义上,可将操作系统定义为一种软件,它控制计算机 ...

  9. 《UNIX环境高级编程(第3版)》

    <UNIX环境高级编程(第3版)> 基本信息 原书名:Advanced Programming in the UNIX Environment (3rd Edition) (Addison ...

最新文章

  1. P1132 数字生成游戏
  2. uploadify控制 上传图片到百度云存储
  3. java程序有连接数据库_Java程序连接数据库
  4. 密码学基础知识(六)Hash函数与消息认证
  5. [html] html5点击返回键怎样不让它返回上一页?
  6. 装入归档文件时出现了一个错误linux_静态链接与动态链接(Linux)
  7. 反转?MIT女博士遭质疑:代码贡献太少,黑洞照片功臣另有其人
  8. DevOps:让开发和运维告别“相爱相杀”
  9. WinServer 2012 R2 搭建域控服务器、文件服务器并配置权限
  10. library/adodb/adodb.inc.php,ADOdb Library for PHP
  11. SpringBoot +esapi 实现防止xss攻击
  12. JAVA设计模式-11-代理模式(动态)(一)
  13. 大学计算机上机实验期末考试题,《大学计算机基础》上机实验报告
  14. 无盘服务器 主板,服务器主板 无盘专用
  15. 《管理经济学》公式大全
  16. 2021年想转行产品经理,应该如何入门?
  17. 计算机组装时各配件的安装顺序,如何组装一台电脑 组装一台电脑配件及步骤【详解】...
  18. 软考中级网络工程师必背考试知识点集锦(三)
  19. 调速阀------电磁阀
  20. java中变量私有化

热门文章

  1. Day15-集成学习-机器学习-案例二:蒸汽量预测(DataWhale)
  2. cloudfront(cloudfront怎么读)
  3. 鹏程万里-----简单的python爬虫
  4. 计算机系统的组成刷题,驾考刷题宝典电脑版2021试题
  5. 红外小目标检测的非对称上下文调制
  6. MSBuild使用初步
  7. Springboot+建筑造价师资格考试应试网站设计与实现 毕业设计-附源码260839
  8. 中投民生:今日A股大面积飘绿;注册制独领风骚
  9. 基于java小区物业管理系统计算机毕业设计源码+系统+lw文档+mysql数据库+调试部署
  10. 三十六计之瞒天过海(第一计)