获取linux系统限制

OS: Ubuntu 22.04.1
gcc: 11.2.0
glibc: 2.35

概述

资源是有限的,所以在程序运行时,操作系统会对程序的很多行为都做了限制,可以把这些限制内容硬编码到程序中,但是很明显会影响程序的可移植性。因为在不同的场景下,某些限制的大小可能是不一样的。

系统限制类型可以分为以下两种:

  • 编译时限制。例如,int类型的最大值取决于硬件和编译器的设计。这种限制通常都记录在头文件中(如<limits.h>)。
  • 运行时限制。这类限制在程序运行时可能会变化,POSIX标准提供了sysconf()/pathconf()/fpathconf()三个函数来获取运行时限制。

在 shell 中,可以使用 getconf 命令获取特定 UNIX 系统中已然实现的限制和选项。参见man getconf

函数说明

1
2
3
4
#include <unistd.h>
long sysconf(int name);
long pathconf(const char* pathname, int name);
long fpathconf(int fd, int name);
  1. pathconf和fpathconf的区别: 前者以路径名为参数,后者以文件描述符为参数
  2. 三个函数中的name参数用于标识待查询的系统限制名称。sysconf函数中,name以_SC_开头,pathconf和fpathconf中name以_PC_开头
  3. 三个函数的返回值:
    1) 如果name参数无效,函数返回-1,并把errno设置为EINVAL。
    2) 如果返回-1,且不改变errno的值,表示该值是不确定的,因此在查询前最好先设置errno为0。
    3) 返回>=0的值为正常返回。
  4. 通常情况下,POSIX要求调用sysconf()获取的值在调用进程的生命周期内应保持不变(在linux系统中,有些合理的例外,如进程能够使用setrlimit来修改进程的资源限制);POSIX没有要求pathconf和fpathconf在进程的生命周期内保持不变。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
$ cat -n 006_sys_limits.c 
#include <unistd.h>
#include <limits.h>
#include "../util_err.h"

static void pr_sysconf(char* msg, int name) {
long val;

fputs(msg, stdout);
errno = 0;
if ((val = sysconf(name)) < 0) {
if (errno != 0){
if (errno == EINVAL) {
fputs(" (not supported)\n", stdout);
} else {
err_sys("sysconf error");
}
} else {
fputs(" (no limit)\n", stdout);
}
} else {
printf(" %ld\n", val);
}
}

static void pr_pathconf(char* msg, char* path, int name) {
long val;

fputs(msg, stdout);
errno = 0;

if ((val = pathconf(path, name)) < 0) {
if (errno != 0){
if (errno == EINVAL) {
fputs(" (not supported)\n", stdout);
} else {
err_sys("pathconf error, path: %s", path);
}
} else {
fputs(" (no limit)\n", stdout);
}
} else {
printf(" %ld\n", val);
}
}

void main() {
printf("_POSIX_ARG_MAX: %d\n", _POSIX_ARG_MAX);
printf("_POSIX_OPEN_MAX: %d\n", _POSIX_OPEN_MAX);
printf("_POSIX_CHILD_MAX: %d\n", _POSIX_CHILD_MAX);
printf("-------\n");
pr_sysconf("arg max:", _SC_ARG_MAX);
pr_sysconf("open max:", _SC_OPEN_MAX);
pr_sysconf("child max:", _SC_CHILD_MAX);
pr_sysconf("pagesize:", _SC_PAGESIZE);
pr_sysconf("clock ticks:", _SC_CLK_TCK);
pr_sysconf("phy pages:", _SC_PHYS_PAGES);
pr_sysconf("avphy pages:", _SC_AVPHYS_PAGES);
pr_sysconf("processor conf:", _SC_NPROCESSORS_CONF);
pr_sysconf("processor online:", _SC_NPROCESSORS_ONLN);

printf("===========\n");
pr_pathconf("name max:", ".", _PC_NAME_MAX);
pr_pathconf("path max:", ".", _PC_PATH_MAX);
pr_pathconf("pipe buff:", ".", _PC_PIPE_BUF);

printf("_POSIX_NAME_MAX: %d\n", _POSIX_NAME_MAX);
printf("_POSIX_PATH_MAX: %d\n", _POSIX_PATH_MAX);
printf("_POSIX_PIPE_BUF: %d\n", _POSIX_PIPE_BUF);
}
$ gcc 006_sys_limits.c ../util_err.c
$ ./a.out
_POSIX_ARG_MAX: 4096
_POSIX_OPEN_MAX: 20
_POSIX_CHILD_MAX: 25
-------
arg max: 2097152
open max: 1024
child max: 15114
pagesize: 4096
clock ticks: 100
phy pages: 995797
avphy pages: 686847
processor conf: 2
processor online: 2
===========
name max: 255
path max: 4096
pipe buff: 4096
_POSIX_NAME_MAX: 14
_POSIX_PATH_MAX: 256
_POSIX_PIPE_BUF: 512
$

运行时限制选项说明

POSIX标准中,对于各选项定义了一个最小值,要求所有的实现都必须大于等于该值,这些宏定义通常以_POSIX_开头,通常包含在<limits.h>头文件中

限制名称 name参数 POSIX最小值 Ubuntu 22.04.1实际值 说明
ARG_MAX _SC_ARG_MAX _POSIX_ARG_MAX(4096) 2097152 exec函数中argv和环境变量environ的最大字节数
CHILD_MAX _SC_CHILD_MAX _POSIX_CHILD_MAX(25) 15114 每个real user ID下的最大进程数
OPEN_MAX _SC_OPEN_MAX _POSIX_OPEN_MAX(20) 1024 每个进程可以同时打开的文件描述符的数量
PAGESIZE _SC_PAGESIZE NA 4096 系统的页大小,单位byte
时钟每秒滴答数 _SC_CLK_TCK NA 100
_SC_NPROCESSORS_CONF NA 无参考意义 配置的处理器个数
_SC_NPROCESSORS_ONLN NA 无参考意义 当前可获得的处理器个数
_SC_PHYS_PAGES NA 无参考意义 物理内存总page数
_SC_AVPHYS_PAGES NA 无参考意义 当前可获得的物理内存page数
NAME_MAX _PC_NAME_MAX _POSIX_NAME_MAX(14) 255 针对目录有效,返回该目录下文件命名的最大长度,对于其他文件类型,则未作规定
PATH_MAX _PC_PATH_MAX _POSIX_PATH_MAX(256) 4096 针对目录有效,返回该目录中相对路径名的最大长度,对于其他文件类型,则未作规定
PIPE_BUF _PC_PIPE_BUF _POSIX_PIPE_BUF(512) 4096 针对目录、FIFO或管道有效,对于 FIFO 或者管道,返回一个应用于对应FIFO或管道的值。对于目录,返回的值应用于在该目录下创建的任一FIFO的限制值。对于其他文件类型,则未作规定

不确定的运行时限制