每一个UNIX的实现集都有很多系统特性和资源的限制并且提供或者不提供有不同标准定义的选项。比如说
- 一个进程可以同一时间处理多少个打开文件?
- 是否系统支持时实信号?
- 存储在int类型中的最大值是多少?
- 一个程序最多可以有多少个输入参数?
- 路径名最大长度是多少?
假设我们将这些限制和选项hard code进应用程序的时候,他就会降低可移植性,因为限制和选项会发生变化。
- 跨UNIX实现:尽管限制和选项可能固定在一个单独的UNIX上,但是他们毕竟在不同的UNIX实现上不尽相同。
- 在特殊实现中的run-time:内核可能会被重配置来改变一个限制。另外,程序可能在一个系统上被编译,但是却运行在有不同限制和选项的其他系统上。
- 从一个文件系统到另一个:比如,传统的System V文件系统允许一个文件名长达14字节,但是传统的BSD系统和最原始的Linux文件系统却允许高达255字节。
因为系统限制和选项会影响应用程序会做什么,一个可移植程序需要方法确认限制值以及是否选项支持。所以在SUSv3当中提供了两种主要的方案可以让应用程序获得以下信息:
- 一些限制和选项可以在编译的时候被决定,比如,int的最大值由硬件结构和编译选项所决定。这些限制会放在头文件里说明。
- 另外一些限制和选项在运行时候会改变。比如SUSv3定义了三个函数-sysconf(),pathconf()还有fpathconf()-他们可以让应用程序调用并检查这些实现的目前的限制和选项是什么。
11.1 系统限制
对于每一个所定义的限制,SUSv3都需要所有实现都对每一个limit有最小值的支持。在大多数例子当中,最小值被定义在<limits.h>当中,并带有前缀_POSIX_,并且通常包含了字符串_MAX;因此,它的形式就是_POSIX_XXX_MAX。
读到这里,一般会对这个MAX感到困惑,这是因为在定义的时候大家认为这个应该用来限制一些资源或者特性的上限值,所以对于定义的人来说这个就是一个上限值的最小值。
如果一个应用限制自己到SUSv3所规定的每一个限制的最小值上面,那么他就会对于所有该标准的实现都具有可移植性。但是,这样子就会导致由更高更强力的系统被限制使用它的优势。就这个原因来说,一般对于特定系统更倾向于使用<limits.h>, sysconf()或者pathconf()来确定limit和option。
每一个限制都有一个名字相应于上面所说的最小值名字,只是不带_POSIX_前缀。一个实现可能将这个名字定义在了<limits.h>来表示它的相应限制。
如果定义了的话,这个限制一般会使用一个最小值检查(和POSIX最小值相比较),一般系统都要大于等于带_POSIX_的值,比如XXX_MAX >= _POSIX_XXX_MAX。
SUSv3将所定义的限制分成三类:运行不变值,路径名称变量还有运行时可增长值。我们会在下面小节中具体讲解每一种分类。
运行时不变值
一个运行时不可变值是一个定义在<limits.h>的固定值。然而这个值也有可能是未定(也许因为取决于剩余内存空间),并且因此在<limits.h>当中被忽略。在这种情况下(即使已经在<limits.h>中被定义过),一个应用程序也可以通过sysconf()在运行过程决定它的值。
比如说MQ_PRIO_MAX限制是一个运行时不变值得例子。在52.5.1中可以看到更具体地讲解和应用。这是一个限制POSIX信息队列限制信息优先级地东西。SUSv3定义了常数_POSIX_MQ_PRIO_MAX