问题引入
POSIX限制和XSI限制,规定了一些系统实现必须支持的最小值,比如<limits.h>中的POSXI.1规定_POSIX_OPEN_MAX(每个进程打开文件数)最小值为20,_POSIX_PATH_MAX(路径名中的字节数,包括null 终结符)最小为256,而XSI规定_XOPEN_PATH_MAX(路径名中的字节数)最小值为1024。然而具体的系统实现,其支持的限制值不一定就是最小值。那么问题来了,如何才能找到一个特定系统实际支持的限制值呢?
限制值分类
限制值根据运行时是否可变,分为两类,分别使用不同的办法确定实际值:
- 某些限制值编译时可用,也就是说在给定系统中不会更改;
通常,直接用一个宏定义就开得到其值。
- 另一些限制值,必须在运行时确定,因为可能与文件或目录关联,运行时可改变;
sysconf, pathconf, fpathconf就是用来确定这类运行时可改变值。
sysconf, pathconf, fpathconf
#include <unistd.h>
long sysconf(int name);
#include <unistd.h>
long fpathconf(int fd, int name);
long pathconf(char *path, int name);
sysconf说明
sysconf获取与系统有关配置信息,非专门的文件相关。其参数name用于标识系统限制,是以_SC_开头的常量(定义在<bits/confname.h>,不过应该include <unistd.h>)。
比如,_SC_OPEN_MAX (限制名OPEN_MAX) 表示每个进程打开的最大文件数,要求 _SC_OPEN_MAX >= _POSIX_OPEN_MAX (20)。
pathconf, fpathconf
pathconf获取与文件相关的配置值。其参数path 根据不同的name,有不同的要求,一般必须是一个文件或目录的路径。其参数name也是用于标识系统限制,是以_PC_开头的常量(位置同sysconf的name参数,也是<bits/confname.h>)。
比如,_PC_PATH_MAX(限制名PATH_MAX)表示当path是当前工作目录时,相对路径名的最大长度,要求 _PC_PATH_MAX >= _POSIX_PATH_MAX (256)
fpathconf 与pathconf基本相同,区别在于fpathconf的参数fd必须是一个已经open的文件描述符。
参数name及返回值
-
如果name不是一个合适的常量,比如取了一个sysconf或pathconf支持的name以外的值,这3个函数都返回-1,且把errno置为EINVAL(参数无效错误)。
-
有些name作为参数,得到一个变量值(>=0)或提示该值不确定。不确定的值,通过返回-1,且不改变errno。
因此,程序获取运行时的限制值时,也要处理不确定值的情况,通常是得到不确定值时猜测一个值。
i.g. 获取NAME_MAX限制值时,如果不确定就默认猜255
// 获取限制NAME_MAX
long name_max = pathconf(".", _PC_NAME_MAX);
if (name_max == -1) {
name_max = 255; // guess
}
// 申请文件名缓存
char *filename = (char *)malloc(name_max + 1); // + 1 for null byte
...
free(filename);
参考
AUPE 第3版 page33~35