1. 前言
无论是哪种系统,可用的资源是有限的,这里的资源包括很多,比如路径长度、文件名长度、可打开文件数、最大子进程数等。
那么我们在开发程序时如何获取到这些限制值以提高程序的可移植性?下面介绍 UNIX 环境下这些值的获取。
2. 介绍
系统限制值分为两类:
- 编译时限制值
ISO C 标准的编译时限制值全部在头文件 <limits.h> 中,包括整数最大、最小值等,POSIX.1 扩充了 ISO C 的限制值,有些定义在 <limits.h> 中,
有些则按具体条件可定义或不定义(可通过下面三个 conf 函数获取)。编译程序时包含这个头文件即可获取编译时限制值; - 运行时限制值(又可分为确定值和不确定值)
必须在程序运行时通过相关函数来获取,与文件或目录无关的限制 值可以通过 sysconf 获取,有关的则通过 pathconf、fpathconf 获取。
3. sysconf、pathconf、fpathconf
3.1 介绍
#include <unistd.h>
long sysconf(int name);
long pathconf(const char *pathname, int name);
long fpathconf(int fd, int name);
三个函数的形参 name 用于标识要获取的限制值,例如 _SC_CLK_TCK(每秒时钟滴答数),_PC_NAME_MAX(文件名的最大字节数,不包括终止字符)。
后两个函数的区别是前者第一个形参是路径名,后者是文件描述符。
3.2 返回值
三个 conf 函数的返回值有如下规定:
- 如果 name 不是一个合适的常量,都返回 -1,并置 errno 为 EINVAL。
- 如果 name 是一个合法常量,但返回 -1 且未改变 errno 的值,说明该限制值是不确定的
- 如果 name 合法,且返回值大于 0,则该值就是限制值。
3.3 pathconf、fpathconf 的注意事项
使用这两个函数时,要注意第一个形参必须满足一定的条件,否则会出现未定义的现象
- _PC_MAX_CANON 和 _PC_MAX_INPUT 对应的 name 引用的文件必须是终端文件
- _PC_LINK_MAX 和 _PC_TIMESTAMP_RESOLUTION 对应的 name 引用的文件可以是文件或目录,如果是目录,返回值只能用于目录本身,而不能用于目录内的文件名项
- _PC_FILESIZEBITS 和 _PC_NAME_MAX 对应的 name 引用的文件必须是目录,返回值用于该目录的文件名项
- _PC_PATH_MAX 对应的 name 引用的文件必须是目录,返回值是相对路径名的最大长度
- _PC_PIPE_BUF 对应的 name 引用的文件必须是管道、FIFO 或目录,若是前两者,则返回对应的限制值;若是目录,返回值则是该目录中创建的任一 FIFO 的限制值
- _PC_SYSLINK_MAX 对应的 name 引用的文件必须是目录,返回值是该目录中符号链接可包含字符串的最大长度
name 参数 | 说明 |
---|---|
_PC_MAX_CANON | 终端规范输入队列的最大字节数 |
_PC_MAX_INPUT | 终端输入队列可用空间的字节数 |
_PC_LINK_MAX | 文件链接技术的最大值 |
_PC_TIMESTAMP_RESOLUTION | 文件时间戳的纳秒精度 |
_PC_FILESIZEBITS | 以带符号整型值表示在指定目录中允许的普通文件最大长度所需的最小位数 |
_PC_PIPE_BUF | 能原子地写到管道的最大字节数 |
_PC_SYSLINK_MAX | 符号链接的字节数 |
4. 不确定的运行时限制值
如果某些限制值未定义在 <limits.h> 中(只能在运行时获取),且值是不确定的,那么在运行时它们可能是未定义的,此时我们应根据三个 conf 的返回值来判断该值是否是未定义的,若是则我们应该赋予一个猜测值,常见的情况为相对路径名的最大字节数(_PC_PATH_MAX)和最大打开文件数(_SC_OPEN_MAX),这两个限制值一般都是不确定的,因此在开发中需要特别注意,后一个的获取问题可以通过 XSI 的 getrlimit 来避开。