从 Linux 中的 /proc 文件系统获取硬件信息

Posted

技术标签:

【中文标题】从 Linux 中的 /proc 文件系统获取硬件信息【英文标题】:Get hardware information from /proc filesytem in Linux 【发布时间】:2017-11-07 01:12:01 【问题描述】:

我使用execv 运行lshw 命令以C 代码获取CPU、磁盘和内存。但我想搜索另一种解决方案以从/proc 或任何其他现有数据中获取这些信息。有什么建议吗?这是我的代码:

char *params[9]  = "/usr/bin/lshw", "-short", "-c", "disk", 
                  "-c", "memory", "-c", "processor", 0; //cmd params filled
execv(params[0], params);

Linux 命令:$ sudo lshw -short -c disk -c processor -c memory

$ sudo lshw -short -c disk -c processor -c memory
H/W path         Device     Class          Description
======================================================
/0/0                        memory         64KiB Bios
/0/22                       memory         16GiB System Memory
/0/22/0                     memory         DIMM Synchronous [empty]
/0/22/1                     memory         DIMM Synchronous [empty]
/0/22/2                     memory         8GiB DIMM Synchronous 2133 MHz (0.5 ns)
/0/22/3                     memory         8GiB DIMM Synchronous 2133 MHz (0.5 ns)
/0/2a                       memory         256KiB L1 cache
/0/2b                       memory         1MiB L2 cache
/0/2c                       memory         6MiB L3 cache
/0/2d                       processor      Intel(R) Xeon(R) CPU D-1521 @ 2.40GHz
/0/1/0.0.0       /dev/sda   disk           16GB SATADOM-SH 3IE3
/0/2/0.0.0       /dev/sdb   disk           120GB Patriot Blaze

我有两个问题:

在哪里可以找到解析/proc中文件的指南以获取 这些硬件信息? 是否需要追踪lshw的源代码才能找到lshw的作用?

编辑:

Advanced Linux Programming 的第 7 章是解析/proc 文件系统的指南。

【问题讨论】:

阅读源代码比跟踪二进制文件更好。 @jww 我的问题是关于如何在纯 C 代码编程中做到这一点。 @Charles - 很抱歉。我应该更加注意。这可能对您的任务有所帮助:lshw filetype:c. 部分信息在/sys/下,不仅在/proc/ @BasileStarynkevitch,是的,你是对的。我刚刚发现lshw/sys/firmware/dmi/tables/读取原始数据,和dmidecode一样。 dmidecode 在 C 中,C 对我来说比 CPP 中的 lshw 容易。 【参考方案1】:

获取硬件信息的最佳方法是在 Linux 上使用 sysconf() 和 sysctl*() 函数(Mac OS X、freebsd、openbsd)以及 sysconf() 和 sysinfo()。

解析 /proc/* 比调用 sysinfo( ) 或 sysconf( ) 更慢且涉及更多

以下是一个小示例,为您提供有关 Mac OS X 上的处理器和内存的一些信息:

#include <sys/types.h>
#include <sys/sysctl.h>
#include <stdio.h>
#include <stdlib.h>
#include <errno.h>
#include <string.h>

int main()

 char *p = NULL;
 size_t len;
 sysctlbyname("hw.model", NULL, &len, NULL, 0);
 p = malloc(len);
 sysctlbyname("hw.model", p, &len, NULL, 0);
 printf("%s\n", p);
 /* CTL_MACHDEP variables are architecture dependent so doesn't work 
 for every one */
 sysctlbyname("machdep.cpu.brand_string", NULL, &len, NULL, 0);
 p = malloc(len);
 sysctlbyname("machdep.cpu.brand_string", p, &len, NULL, 0);
 printf("%s\n", p);
 int64_t mem;
 len = sizeof(mem);
 sysctlbyname("hw.memsize", &mem, &len, NULL, 0);
 printf("System Memory : %lld\n", mem);
 return (0);

您必须阅读 man 3 sysctl,或者在 Linux 上阅读 man 2 sysconf 和 man 2 sysinfo。

一个有趣的链接:http://nadeausoftware.com/articles/2012/09/c_c_tip_how_get_physical_memory_size_system#Other

您可以通过检索一些 sysctl 变量来计算 CPU 负载和使用率,然后自己进行数学运算(您可以在 google 上找到计算公式)。

但是在哪里可以找到物理 DIMM 信息作为来自 $ sudo lshw -short -c memory 的报告?

您可以在 C 程序中执行命令,将其保存为字符串,例如:

#include <stdio.h>
#include <unistd.h>
#include <errno.h>
#include <sys/wait.h>
#include <string.h>
#include <stdlib.h>

char *strjoin(char *s1, char *s2, int n)

    int i = strlen(s2);
    int j = 0;
    if ((s2 = realloc(s2, (i + n + 1))) == NULL)
            perror(0);
    while (j < n && s1[j])
    
            s2[i] = s1[j];
            i++;
            j++;
    
    s2[i] = 0;
    return (s2);


int main()

    pid_t father;
    char buf[500] = 0;
    char *str;
    char *argv[5] = "/usr/bin/lshw", "-short", "-c", "memory";
    int fd[2];
    int ret;

    if (pipe(fd) == -1)
    
            perror(NULL);
            return -1;
    
    father = fork();
    if (father == 0)
    
            close(fd[1]);
            while ((ret = read(fd[0], buf, 500)))
            
                    str = strjoin(buf, str, ret);
            
            close(fd[0]);
    
    else
    
            close(fd[0]);
            execv(argv[0], argv);
            close(fd[1]);
            wait(0);
    
    wait(0);
    printf("%s", str);
    return 0;

(我没有检查这段代码中所有函数的返回值,不要太长,但你应该在你的程序中检查)。

这是一个解析文件 /proc/meminfo 以将我想要的 2 个字符串保存在双数组中,然后将它们打印出来的示例:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

int main()

    FILE *f;
    char *line = NULL;
    ssize_t read;
    size_t len = 0;
    char    **info;
    int i = 0;

    info = malloc(3 * sizeof(char*));
    f = fopen("/proc/meminfo", "r");
    while ((read = getline(&line, &len, f)) != -1)
    
            if (strstr(line, "MemTotal") != NULL)
                    info[i] = strdup(line);
            else if (strstr(line, "MemFree") != NULL)
                    info[i] = strdup(line);
            i++;
    
    info[i] = 0;
    fclose(f);
    i = 0;
    while (info[i])
    
            printf("%s", info[i]);
            free (info[i]);
            i++;
    
    free (info);
    return 0;

如果要保存更多字符串,请在双精度数组信息中分配更多空间,并在读取循环中添加它们与 else if。您可以使用 /proc/ 中的任何文件来获取所需的信息。

【讨论】:

是的,在 Linux 上,函数 sysconf() 和 sysinfo() 更好(man 2)。在我给出的链接中,还有一个解析文件的例子,如果你的信息不是全部在这两个函数中 我已经阅读了手册页中的函数 sysconf() 和 sysinfo() 并阅读了您提供的链接。但我仍然无法得到我想要的。我会尝试阅读lsscsi的代码和lscpu的代码,或者只是解析文件/proc/cpuinfo。但是在哪里可以找到物理 DIMM 信息作为来自$ sudo lshw -short -c memory 的报告。 你可以访问 /dev/mem 吗? 如果您需要帮助解析您需要解析的文件之一,请在此处粘贴其中一个文件内容,我会写一个示例,说明如何解析它以获得您想要的信息跨度> 我修改了我的答案,最后向您展示了如何将 C 中命令的结果保存在字符串中的示例(如果您执行此代码,它将向您输出字符串)。你可以使用任何你想要的命令来做到这一点。【参考方案2】:

通过阅读lshw的源码,发现lshw/sys/class/dmi/读取原始数据。因为lshw是用我不熟悉的CPP写的,所以有一个问题Where does dmidecode get the SMBIOS table?提到dmidecode.c/sys/class/dmi读取原始数据和lshw一样。

这是dmidecode.c中的定义

#define SYS_ENTRY_FILE "/sys/firmware/dmi/tables/smbios_entry_point"
#define SYS_TABLE_FILE "/sys/firmware/dmi/tables/DMI"

我从dmidecode.c提取代码以获取CPU和内存信息,并使用lsscsi获取磁盘信息。

感谢您的帮助。

【讨论】:

【参考方案3】:

1:要获取 CPU 负载,请使用以下命令:

top -bn1 | grep load

这会给你这样的输出:

top - 12:26:20 up 35 min,  2 users,  load average: 0.02, 0.01, 0.00

现在从上面的字符串解析负载平均值。 2:要获取内存信息,请使用此命令:

free -m

这会给你:

total       used       free     shared    buffers     cached
Mem:         15926        308      15617          6         15        122
-/+ buffers/cache:        171      15755
Swap:            0          0          0

要获取磁盘信息,请使用:

df -H /home/test

这会给你:

Filesystem      Size  Used Avail Use% Mounted on
/dev/sda1       102G  5.4G   91G   6% /

现在从上面的结果解析你想要的内容。

【讨论】:

感谢您的信息,但我想用纯 C 代码来做。 将上述命令的输出重定向到文件,然后解析该文件中的数据。对于重定向使用 dup2() 系统调用。例如int fd = 打开(文件,O_RDWR | O_CREAT,S_IRUSR | S_IWUSR);然后复制 I/O 缓冲区的 file_descriptor。 e. G。 dup2(fd, 1); // 使标准输出转到文件和 dup2(fd, 2); // 使 stderr 转到文件。

以上是关于从 Linux 中的 /proc 文件系统获取硬件信息的主要内容,如果未能解决你的问题,请参考以下文章

linux 使用 /proc 文件系统

/proc文件系统

linux查看硬件信息

Linux下的/proc目录介绍

深入理解linux系统下proc文件系统内容

Linux下proc文件接口详解