系统限制和选项:sysconf 函数详解

Linux系统的实现需要遵循很多个标准,比如ANSI C标准,POSIX标准,XSI标准,每个标准都有各自的限制和选项,标准中规定有一些内容是必须的,一些是可选的。当我们的应用程序设计遵循标准中的选项和限制,那么就可以达到最大化的可移植性。

静态定义

不管是限制还是选项,都是支持静态和动态获取的,也有一些只能在系统运行后才能确定其值的,那么就只有通过动态去获取了。对于静态定义的系统限制和选项,宏定义都会包含在如下头文件中:

#include <unistd.h>
#include <limit.h>

limit.h 头文件会包含限制相关的定义,unistd.h 头文件会包含选项相关的定义。

动态获取

Linux系统中基本上所有的限制和选项都可以通过sysconf函数在运行时获取:

#include <unistd.h>

long sysconf(int name);
long pathconf(const char *pathname, int name);
long fpathconf(int fd, int name);

系统定义了所有相关的name宏定义,格式为:_SC_XXX/_PC_XXX,其中 _SC_XXX 是给 sysconf 使用的;_PC_XXX 是给 pathconf 和 fpathconf 使用的。
比如:

_SC_ARG_MAX
......
_PC_FILESIZEBITS

返回值:

  1. 如果传入的name值该函数不支持,则返回 -1 ,并把errno设置为EINVAL。
  2. 返回 -1 ,errno为0,表示是不确定的或者无限制的
  3. 返回 >= 0 ,为设定的一个确定的值,在进程运行过程中是不改变的。

如上所说,系统限制和选项在进程运行过程中是不改变的,因此我们只有获取config的API,却没有修改的API。但有一点需要注意的是,rlimit中有两个值的修改会影响到对应的sysconf获取的值:

RLIMIT_NOFILE 会反映到sysconf的_SC_OPEN_MAX的返回值。
RLIMIT_NPROC 会反映到sysconf的_SC_CHILD_MAX的返回值。

所有能够使用的sysconf参数可以通过头文件 confname.h 中去查找:

 /* Values for the NAME argument to `pathconf' and `fpathconf'.  */
 enum
   {
     _PC_LINK_MAX,
 #define _PC_LINK_MAX            _PC_LINK_MAX
     _PC_MAX_CANON,
 #define _PC_MAX_CANON           _PC_MAX_CANON
     _PC_MAX_INPUT,
 #define _PC_MAX_INPUT           _PC_MAX_INPUT
     _PC_NAME_MAX,
 #define _PC_NAME_MAX            _PC_NAME_MAX
     _PC_PATH_MAX,
 #define _PC_PATH_MAX            _PC_PATH_MAX
     _PC_PIPE_BUF,
......
   };

 /* Values for the argument to `sysconf'.  */
 enum
   {
     _SC_ARG_MAX,
 #define _SC_ARG_MAX         _SC_ARG_MAX
     _SC_CHILD_MAX,
 #define _SC_CHILD_MAX           _SC_CHILD_MAX
     _SC_CLK_TCK,
 #define _SC_CLK_TCK         _SC_CLK_TCK
     _SC_NGROUPS_MAX,
 #define _SC_NGROUPS_MAX         _SC_NGROUPS_MAX
     _SC_OPEN_MAX,
 #define _SC_OPEN_MAX            _SC_OPEN_MAX
     _SC_STREAM_MAX,
 #define _SC_STREAM_MAX          _SC_STREAM_MAX
     _SC_TZNAME_MAX,
 #define _SC_TZNAME_MAX          _SC_TZNAME_MAX
     _SC_JOB_CONTROL,
 #define _SC_JOB_CONTROL         _SC_JOB_CONTROL
     _SC_SAVED_IDS,
 #define _SC_SAVED_IDS           _SC_SAVED_IDS
     _SC_REALTIME_SIGNALS,
   ......
   };

限制

对于系统限制来说,一般会定义一个对应的宏在 limit.h 头文件中,比如 _FOO ,同时也会定义 sysconf() 参数宏 _SC_FOO 用于给 sysconf 函数动态获取使用。
对于一个限制来说,POSIX标准定义了针对该限制的所能允许设置的最小值 _POSIX_FOO,实际系统对于限制 _FOO 的设定只要满足比该值更大,所以 _POSIX_FOO 只能作为 _FOO 的极限值。

测试示例:

#ifdef ARG_MAX
	printf("ARG MAX is defined to %ld\n", (long) ARG_MAX);
#else
	printf("no symbol for ARG_MAX\n");
#endif

#ifdef _SC_ARG_MAX
	printf("ARG_MAX = %ld, errno:%d\n", sysconf(_SC_ARG_MAX), errno);
#else
	printf("no symbol for _SC_ARG_MAX\n");
#endif

通过类似上述代码片段的实现,我们可以打印出当前系统都做了哪些限制,可以看到和 ARG_MAX 限制对应的 sysconf 参数宏被定义为 _SC_ARG_MAX。我的部分测试结果:

no symbol for ARG_MAX
ARG_MAX = 2097152, errno:0
no symbol for ATEXIT_MAX
ATEXIT_MAX = 2147483647, errno:0

从这份测试结果可以看出, ARG_MAX 和 ATEXIT_MAX 这两个限制都没有定义对应的静态值,而需要通过运行时确定。因此使用时需要特别注意:如果没有静态定义,也必须要使用动态获取接口尝试获取一下。

选项

对应选项的定义和limit限制还是稍有区别,一般是会在 unistd.h 头文件中定义 _POSIX_FOO ,同时定义 sysconf() 参数宏 _SC_FOO 用于给 sysconf 函数动态获取使用。和限制一样,对于一个特定的选项,如果没有静态定义,我们也必须要使用动态获取接口尝试。

#ifdef _POSIX_BARRIERS
     printf("_POSIX_BARRIERS is defined (val is %ld)\n", (long)_POSIX_BARRIERS+0);
#else
     printf("_POSIX_BARRIERS is undefined\n");
#endif
#ifdef _SC_BARRIERS
	 printf("_POSIX_BARRIERS = %ld, errno:%d\n", sysconf(_SC_BARRIERS), errno);
#else
     printf("no symbol for _POSIX_BARRIERS\n");
#endif

测试结果:

_POSIX_BARRIERS is defined (val is 200809)
sysconf says _POSIX_BARRIERS = 200809
  • 2
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值