在程序设计中,有时经常需要获取系统的一些信息,比如系统中有几个CPU,有多少内存,内核版本是多少等等。在Linux中,虽然绝大部分信息都可以通过/proc来获取,但是直接取操作/proc文件容易依赖于特定内核。因此更好的方法是通过一些API来实现以提高可移植性。本文总结用来获取系统信息的一些常用API。
sysconf函数
该函数的原型如下:
#include <unistd.h>
long sysconf(int name);
这个函数可以用来定义POSIX编程标准定义的一些配置。下面是一些例子:
- _SC_ARG_MAX: 能传递个exec函数组的参数的最大长度
- _SC_NPROCESSORS_CONF:系统中的处理器个数
- _SC_NPROCESSORS_ONLN: 在线的处理器个数
- _SC_PAGESIZE:页面大小
- _SC_VERSION:POSIX.1标准的版本(日期形式)
- _SC_2_VERSION:POSIX.2标准的版本(日期形式)
confstr函数
此函数原型如下:
#include <unistd.h>
size_t confstr(int name, char *buf, size_t len);
该函数与sysconf类似,只不过返回的是字符串信息的配置。常用的配置包括:
- _CS_GNU_LIBC_VERSION:glibc的版本
- _CS_GNU_LIBPTHREAD_VERSION:pthread库版本
- _CS_PATH:PATH环境变量
pathconf函数
此函数原型如下:
#include <unistd.h>
long fpathconf(int fd, int name);
long pathconf(const char *path, int name);
该函数的作用是获取与指定路径相关的一些配置,比如:
- _PC_PATH_MAX:相对与path的路径的最大长度
- _PC_NAME_MAX:在path指定的路径中允许的文件名的最大长度
- _PC_PIPE_BUF:能够向一个管道或者FIFO里写入的最大字节数
- _PC_LINK_MAX:对指定的path,允许的最大链接数
sysctl系统调用
sysctl系统调用提供了获取/proc/sys下的配置的方便方式。不过glibc中并没有对该系统调用进行封装,因此必须使用原始的系统调用的方式,比较麻烦。不过,Linux系统一般都带了sysctl工具,可以方便的获取或设置所有sysctl的信息。
简单例子
下面是一个简单的例子,覆盖了上述API的使用。
#include <sys/param.h>
#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
int main(int argc, char *argv[])
{
char buf[MAXPATHLEN] = {"/"};
/* sysconf: _SC_XXX */
printf("NPROCESSORS_CONF: %ld\n", sysconf(_SC_NPROCESSORS_CONF));
printf("NPROCESSORS_ONLN: %ld\n", sysconf(_SC_NPROCESSORS_ONLN));
printf("PAGESIZE: %ld\n", sysconf(_SC_PAGESIZE));
printf("CLK_TCK: %ld\n", sysconf(_SC_CLK_TCK));
printf("ARG_MAX: %ld\n", sysconf(_SC_ARG_MAX));
printf("CHILD_MAX: %ld\n", sysconf(_SC_CHILD_MAX));
printf("OPEN_MAX: %ld\n", sysconf(_SC_OPEN_MAX));
printf("POSIX.1: %ld\n", sysconf(_SC_VERSION));
printf("POSIX.2: %ld\n", sysconf(_SC_2_VERSION));
/* pathconf: _PC_XXX */
printf("PATH_MAX: %ld\n", pathconf(buf, _PC_PATH_MAX));
printf("NAME_MAX: %ld\n", pathconf(buf, _PC_NAME_MAX));
printf("PIPE_BUF: %ld\n", pathconf(buf, _PC_PIPE_BUF));
printf("LINK_MAX: %ld\n", pathconf(buf, _PC_LINK_MAX));
/* confstr: _CS_XXX */
#if defined(__GLIBC__)
confstr(_CS_GNU_LIBC_VERSION, buf, sizeof(buf));
printf("GNU_LIBC_VERSION: %s\n", buf);
confstr(_CS_GNU_LIBPTHREAD_VERSION, buf, sizeof(buf));
printf("GNU_LIBPTHREAD_VERSION: %s\n", buf);
#endif
confstr(_CS_PATH, buf, sizeof(buf));
printf("PATH: %s\n", buf);
/* sysctl */
system("sysctl kernel.ostype");
system("sysctl kernel.osrelease");
system("sysctl kernel.version");
return 0;
}
gcc -o sysinfo sysinfo.c
./sysinfo
NPROCESSORS_CONF: 4
NPROCESSORS_ONLN: 4
PAGESIZE: 4096
CLK_TCK: 100
ARG_MAX: 2097152
CHILD_MAX: 63764
OPEN_MAX: 1024
POSIX.1: 200809
POSIX.2: 200809
PATH_MAX: 4096
NAME_MAX: 255
PIPE_BUF: 4096
LINK_MAX: 65000
GNU_LIBC_VERSION: glibc 2.27
GNU_LIBPTHREAD_VERSION: NPTL 2.27
PATH: /bin:/usr/bin
kernel.ostype = Linux
kernel.osrelease = 5.4.0-56-generic
kernel.version = #62~18.04.1-Ubuntu SMP Tue Nov 24 10:07:50 UTC 2020