C 获取Linux系统信息

该代码来源于fedora的官方文档,源码地址:https://github.com/xbcsmith/cli-app

// Node Info Cli App
#include <sys/utsname.h>
#include <stdio.h>
#include <stdlib.h>
#include <errno.h>

int main()
{
    // define utsname struct
    struct utsname info;
    // call uname() and check call
    if (uname(&info) < 0)
    {
        // error if call fails
        perror("uname");
        fprintf(stderr, "Error in uname : %d\n", errno);
        exit(EXIT_FAILURE);
    }
    else
    {
        // Print Node Info
        printf("Node Info\n----------\n");
        printf("node : %s\n", info.nodename);
        printf("system : %s\n", info.sysname);
        printf("version : %s\n", info.version);
        printf("release : %s\n", info.release);
        printf("arch : %s\n", info.machine);
        exit(EXIT_SUCCESS);
    }
}

编译运行可以获取系统信息:

$ gcc nodeinfo.c -o nodeinfo
$ ./nodeinfo
Node Info
----------
node : fedora
system : Linux
version : #1 SMP Wed Jun 23 16:18:11 UTC 2021
release : 5.12.13-300.fc34.x86_64
arch : x86_64

其中utsname.h 和 errno.h 不太熟悉

utsname.h

这个文件是在/usr/include/sys下的,所以导入的时候应该是

#include <sys/utsname.h>

该头文件中定义了一个utsname结构,该结构包含有以下几个属性:

/* Structure describing the system and machine.  */
struct utsname
  {
    /* Name of the implementation of the operating system.  */
    char sysname[_UTSNAME_SYSNAME_LENGTH];

    /* Name of this node on the network.  */
    char nodename[_UTSNAME_NODENAME_LENGTH];

    /* Current release level of this implementation.  */
    char release[_UTSNAME_RELEASE_LENGTH];
    /* Current version level of this release.  */
    char version[_UTSNAME_VERSION_LENGTH];

    /* Name of the hardware type the system is running on.  */
    char machine[_UTSNAME_MACHINE_LENGTH];

#if _UTSNAME_DOMAIN_LENGTH - 0
    /* Name of the domain of this node on the network.  */
# ifdef __USE_GNU
    char domainname[_UTSNAME_DOMAIN_LENGTH];
# else
    char __domainname[_UTSNAME_DOMAIN_LENGTH];
# endif
#endif
  };

还有一个与之配套的函数uname,传入一个指向utsname的指针用来初始化这个结构

/* Put information about the system in NAME.  */
extern int uname (struct utsname *__name) __THROW;

具体的文档在:https://pubs.opengroup.org/onlinepubs/007908775/xsh/uname.html

成功执行uname返回一个非负值,否则返回-1并设置errno指定错误信息,所以在代码中,我们能看到用if判断是否返回非负值,并将异常打印出来。

errno.h

该头文件中定义了一个名叫errno的宏,通常是一个正整数代表一个错误代码,初始值是0。一些库函数通过写入正整数到errno来指定错误。定义在stdio.h的两个函数perror和strerror可以获取当前的erron的值。

/* The error code set by various library functions.  */
extern int *__errno_location (void) __THROW __attribute_const__;
# define errno (*__errno_location ())

举个例子,math.h库通过将错误设置成对应的正整数写入errno,以此来指定错误。

#include <stdio.h>
#include <math.h>
#include <errno.h>

void show_errno(void)
{
    const char *err_info = "unknown error";
    switch (errno)
    {
    case EDOM:
        err_info = "domain error";
        break;
    case EILSEQ:
        err_info = "illegal sequence";
        break;
    case ERANGE:
        err_info = "pole or range error";
        break;
    case 0:
        err_info = "no error";
    }
    fputs(err_info, stdout);
    puts(" occurred");
}

int main(void)
{
    fputs("MATH_ERRNO is ", stdout);
    puts(math_errhandling & MATH_ERRNO ? "set" : "not set");

    errno = 0;
    1.0 / 0.0;
    show_errno();

    errno = 0;
    acos(+1.1);
    show_errno();

    errno = 0;
    log(0.0);
    show_errno();

    errno = 0;
    sin(0.0);
    show_errno();
}

其中每个大写的宏都对应一个正整数,在出现相应错误时,会将其赋值给errno

编译运行结果为:

$ gcc errno_test.c -o errno_test
$ ./errno_test 
MATH_ERRNO is set
no error occurred
domain error occurred
pole or range error occurred
no error occurred
上一篇:FileNotFoundError: [Errno 2] No such file or directory:‘fer2013.csv‘


下一篇:FileNotFoundError: [Errno 2] No such file or directory: ‘XXX‘ 的解决方法