Skip to content

Latest commit

 

History

History
419 lines (214 loc) · 13.2 KB

README.md

File metadata and controls

419 lines (214 loc) · 13.2 KB

SystemInfomationAPIsGuides

languages: English documentation

旨在为了简化开发人员需要获取系统信息时的搜索过程。本仓库提供了常见的信息如系统名称、网络适配器地址、磁盘容量的API小Demo,并叙述了写这些API时容易进入的误区。提供的Demo通常包括Windows平台(在Windows10上测试)和Linux平台(在kernel版本5+上测试)。能够获取的信息如下目录。欢迎各位系统软件开发者提出需求或补充Demo。


目录


Windows

系统基本信息

电脑名称与全称

显示结果:

computer name: DESKTOP-ABCD
computer full name: aa.bb.DESKTOP-ABCD

API文档:

GetComputerNameA function (winbase.h) - Win32 apps | Microsoft Docs

GetComputerNameExA function (sysinfoapi.h) - Win32 apps | Microsoft Docs

当前系统登陆的用户名

显示结果:

login user name: Alice

API文档:

GetUserNameA function (winbase.h) - Win32 apps | Microsoft Docs

系统版本

显示结果:

OS version: Windows10

注意:

版本信息在VersionHelpers.h里通过类似IsWindows10OrGreater()IsWindowsServer()来获取,但是这个API目的是为了测试软件的兼容性而不是获取版本,Windows8及以上依赖于manifest list,若没有此文件,此API只会得到系统版本是Windows8的结果。

***** For applications that have been manifested for Windows 8.1 or Windows 10. Applications not manifested for Windows 8.1 or Windows 10 will return the Windows 8 OS version value (6.2). To manifest your applications for Windows 8.1 or Windows 10, refer to Targeting your application for Windows.

因此如要得到更加详细的信息需要通过RtlGetVersion动态获取。

Operating System Version - Win32 apps | Microsoft Docs

CPU利用率

显示结果:

CPU utilization: 50.0

注意:

一种常规的思路是根据CPU运行的空闲时间和忙碌时间来算出使用率,在Linux上确实是这么算的。但是Windows上若要和任务管理器里显示的值对比,发现此计算的值会小一些。原因是“利用率”的定义问题,任务管理器中利用率实际上是结合了CPU当前频率算出来的,而不是简单的根据CPU时间计算。幸运的是我们不需要知道算法,在性能监视器里可以直接拿到这个值。

我们可以在性能监视器里看到,一个是Processor Time,还有一个是Processor UtilityProcessor Time是根据CPU运行的空闲时间和忙碌时间来算出来的,而Processor Utility才是任务管理器里显示的数值。通过性能计数器,我们可以拿到此数值。

Using Performance Counters - Win32 apps | Microsoft Docs

内存使用情况

显示结果:

memory total size: 7.8GB
memory used size: 5.8GB

API文档:

GlobalMemoryStatusEx function (sysinfoapi.h) - Win32 apps | Microsoft Docs

系统时间和运行时间

显示结果:

system now time: 2022-1-31-15-30
system has run: 10932s

API文档:

GlobalMemoryStatusEx function (sysinfoapi.h) - Win32 apps | Microsoft Docs

GetTickCount64 function (sysinfoapi.h) - Win32 apps | Microsoft Docs

网络适配器信息

网卡IP地址、MAC地址、状态

显示结果:

IPv4 address: 192.168.1.30
MAC address: 1f:2d:3c:4d:5f:6e
status: OK

注意:

此API会返回一个链表,该链表会列出所有网络适配器包括虚拟网络适配器(如虚拟机、回环地址)的信息,包括IP地址和MAC地址,IP地址可能会有多个,应注意遍历全部。此外,IPv4和IPv6的传入FLAG不同,返回的是不同的链表。

GetAdaptersAddresses function (iphlpapi.h) - Win32 apps | Microsoft Docs

网卡上传下载速率

显示结果:

upload rate: 10.1KB/
download rate: 16.0KB/s

注意:

GetAdaptersAddressesAPI返回的链表的节点中有Speed字段,但此字段是指网卡的最大速率。要想获得传输速率需要读取电脑全部的物理接口,获得累积的流量信息,自行计算。此GetIfTableAPI会返回所有物理接口,因此需要根据MAC地址筛选网卡的接口。

GetIfTable function (iphlpapi.h) - Win32 apps | Microsoft Docs

硬盘信息

硬盘名称、总空间、剩余空间

显示结果:

disk name: C:/, total space: 503.13GB, free space: 345.23GB

API文档:

GetLogicalDriveStringsW function (fileapi.h) - Win32 apps | Microsoft Docs

GetDiskFreeSpaceExA function (fileapi.h) - Win32 apps | Microsoft Docs


Linux

前言

Linux系统不像Windows那样有便捷的、统一的API可以直接拿到数据,大多数也没有很完美的实现案例。这里列举出几种实现思路。

  1. 使用shell命令

    shell命令嵌入到程序中执行,然后保存结果。这种方法的优点是很简单,系统的shell命令已经帮我们做了海量的处理。缺点是只能拿到字符数据,需要自己解析,另外使用这种方法实质上是在后台新建进程通过bin/sh运行命令然后拿到输出字符。这种方法涉及到进程的上下文切换开销较大,与直接调用具体功能的API有百倍速度差距。若不考虑性能问题,使用这种方法最为方便。

    具体API如下

    popen(3) - Linux manual page (man7.org)

  2. 读取/proc文件系统里的文件

    /proc是一个在RAM里的临时的文件系统,保存着系统运行的信息。我们可以通过读取文件然后拿到数据,这种方法虽然也伴随着文件的读写,会产生IO中断,但是比方法1相比性能消耗会小一些。

  3. 使用用户API

    这种方法类似于Windows获取信息的方法,利用系统提供的用户API获取到较为原始的信息。直接调用API性能消耗会比较小。

  4. 使用内核API

    这种方法最接近底层,性能消耗最小,但是编程复杂度大幅度提升。

总的来说,从性能优秀程度上来看方法1<2<3<4,从获取信息的方便程度上1>2>3>4。本手册主要使用方法2和方法3,即读取/proc文件系统和用户API。

系统基本信息

电脑名称与全称

显示结果:

computer name: Ubuntu
computer full name: Unbuntu.aa.bb

API文档:

uname(2) - Linux manual page (man7.org)

当前系统登陆的用户名

显示结果:

login user name: Alice

API文档:

getuid(2) - Linux manual page (man7.org)

getpwuid(3p) - Linux manual page (man7.org)

系统版本

显示结果:

OS version: Ubuntu

注意:

这里获取到的是内核版本。

[uname(2) - Linux manual page (man7.org)](https://docs.microsoft.com/en-us/windows/win32/sysinfo/operating-system-version)

CPU利用率

显示结果:

CPU utilization: 50.0

注意:

根据CPU运行的空闲时间和忙碌时间来算出使用率,这里需要从/proc文件系统里读取CPU统计数据进行计算。

文件路径为:/proc/stat

内存使用情况

显示结果:

memory total size: 7.8GB
memory used size: 7.8GB=

API文档:

sysinfo(2) - Linux manual page (man7.org)

系统时间和运行时间

显示结果:

system now time: 2022-1-31-15-30
system has run: 10932s

API文档:

time(2) - Linux manual page (man7.org)

gmtime(3p) - Linux manual page (man7.org)

sysinfo(2) - Linux manual page (man7.org)

网络适配器信息

网卡名称、网卡IPv4地址、IPv6地址、状态、网卡上传下载速率

显示结果:

NIC name: eth0
status: OK
IPv4 address: 192.168.1.30
IPv6 address: 2001:db8:85a3:8d3:1319:8a2e:370:7348
upload rate: 10.1KB/s
download rate: 16.0KB/s

注意:

此API会返回一个链表,该链表会列出所有网络适配器包括虚拟网络适配器(如虚拟机、回环地址)的信息,包括名称、IPv4地址、IPv6地址、传输字节数。但是这里每个网卡的每一项都是单独的一个链表节点,同一个网卡的链表节点具有相同的名字,但根据FLAG的不同而存储不同项。因此需要遍历全部才能收集齐一个网卡的信息。

getifaddrs(3) - Linux manual page (man7.org)

MAC地址

显示结果:

MAC address: 1f:2d:3c:4d:5f:6e

注意:

使用ioctl来获取接口的硬件地址,需要实现创建socket,通过该socket和网卡名称来获取MAC地址。

ioctl(2) - Linux manual page (man7.org)

硬盘信息

硬盘名称、挂载路径、总空间、剩余空间

显示结果:

disk name: dev/sda2, mount path: /, total space: 503.13GB, free space: 345.23GB

注意:

本结果通过读取/proc/mounts拿到所有磁盘的名称和挂载路径,再通过statfs查询挂载路径的空间。

statfs(2) - Linux manual page (man7.org)