该代码来源于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