有时候需要在工程里面获取一些系统或者硬件的信息,比如系统版本,cpu,内存,显卡,硬盘,网络等,作为后续软件功能判断的依据,甚至参与性能算法自适应建模
Windows
操作系统和内存信息在windows下通过系统的API来获取,CPU信息则需要需要通过底层CPUID指令取得
代码:
#include <iostream>
#include <string>
#include <string.h>
#include <winsock2.h> // include must before window.h
#include <iphlpapi.h>
#include <windows.h>
#pragma comment(lib, "iphlpapi.lib")
#pragma warning(disable: 4996) // avoid GetVersionEx to be warned
// ***** global macros ***** //
static const int kMaxInfoBuffer = 256;
#define GBYTES 1073741824
#define MBYTES 1048576
#define KBYTES 1024
#define DKBYTES 1024.0
// ---- get os info ---- //
void getOsInfo()
{
// get os name according to version number
OSVERSIONINFO osver = { sizeof(OSVERSIONINFO) };
GetVersionEx(&osver);
std::string os_name;
if (osver.dwMajorVersion == 5 && osver.dwMinorVersion == 0)
os_name = "Windows 2000";
else if (osver.dwMajorVersion == 5 && osver.dwMinorVersion == 1)
os_name = "Windows XP";
else if (osver.dwMajorVersion == 6 && osver.dwMinorVersion == 0)
os_name = "Windows 2003";
else if (osver.dwMajorVersion == 5 && osver.dwMinorVersion == 2)
os_name = "windows vista";
else if (osver.dwMajorVersion == 6 && osver.dwMinorVersion == 1)
os_name = "windows 7";
else if (osver.dwMajorVersion == 6 && osver.dwMinorVersion == 2)
os_name = "windows 10";
std::cout << "os name: " << os_name << std::endl;
std::cout << "os version: " << osver.dwMajorVersion << '.' << osver.dwMinorVersion << std::endl;
}
// ---- get cpu info ---- //
#ifdef _WIN64
// method 2: usde winapi, works for x86 and x64
#include <intrin.h>
void getCpuInfo()
{
int cpuInfo[4] = {-1};
char cpu_manufacture[32] = { 0 };
char cpu_type[32] = { 0 };
char cpu_freq[32] = { 0 };
__cpuid(cpuInfo, 0x80000002);
memcpy(cpu_manufacture, cpuInfo, sizeof(cpuInfo));
__cpuid(cpuInfo, 0x80000003);
memcpy(cpu_type, cpuInfo, sizeof(cpuInfo));
__cpuid(cpuInfo, 0x80000004);
memcpy(cpu_freq, cpuInfo, sizeof(cpuInfo));
std::cout << "CPU manufacture: " << cpu_manufacture << std::endl;
std::cout << "CPU type: " << cpu_type << std::endl;
std::cout << "CPU main frequency: " << cpu_freq << std::endl;
}
#else
// mothed 1: this kind asm embedded in code only works in x86 build
// save 4 register variables
DWORD deax;
DWORD debx;
DWORD decx;
DWORD dedx;
// init cpu in assembly language
void initCpu(DWORD veax)
{
__asm
{
mov eax, veax
cpuid
mov deax, eax
mov debx, ebx
mov decx, ecx
mov dedx, edx
}
}
long getCpuFreq()
{
int start, over;
_asm
{
RDTSC
mov start, eax
}
Sleep(50);
_asm
{
RDTSC
mov over, eax
}
return (over - start) / 50000;
}
std::string getManufactureID()
{
char manuID[25];
memset(manuID, 0, sizeof(manuID));
initCpu(0);
memcpy(manuID + 0, &debx, 4); // copy to array
memcpy(manuID + 4, &dedx, 4);
memcpy(manuID + 8, &decx, 4);
return manuID;
}
std::string getCpuType()
{
const DWORD id = 0x80000002; // start 0x80000002 end to 0x80000004
char cpuType[49];
memset(cpuType, 0, sizeof(cpuType));
for (DWORD t = 0; t < 3; t++)
{
initCpu(id + t);
memcpy(cpuType + 16 * t + 0, &deax, 4);
memcpy(cpuType + 16 * t + 4, &debx, 4);
memcpy(cpuType + 16 * t + 8, &decx, 4);
memcpy(cpuType + 16 * t + 12, &dedx, 4);
}
return cpuType;
}
void getCpuInfo()
{
std::cout << "CPU manufacture: " << getManufactureID() << std::endl;
std::cout << "CPU type: " << getCpuType() << std::endl;
std::cout << "CPU main frequency: " << getCpuFreq() << "MHz" << std::endl;
}
#endif
// ---- get memory info ---- //
void getMemoryInfo()
{
std::string memory_info;
MEMORYSTATUSEX statusex;
statusex.dwLength = sizeof(statusex);
if (GlobalMemoryStatusEx(&statusex))
{
unsigned long long total = 0, remain_total = 0, avl = 0, remain_avl = 0;
double decimal_total = 0, decimal_avl = 0;
remain_total = statusex.ullTotalPhys % GBYTES;
total = statusex.ullTotalPhys / GBYTES;
avl = statusex.ullAvailPhys / GBYTES;
remain_avl = statusex.ullAvailPhys % GBYTES;
if (remain_total > 0)
decimal_total = (remain_total / MBYTES) / DKBYTES;
if (remain_avl > 0)
decimal_avl = (remain_avl / MBYTES) / DKBYTES;
decimal_total += (double)total;
decimal_avl += (double)avl;
char buffer[kMaxInfoBuffer];
sprintf_s(buffer, kMaxInfoBuffer, "total %.2f GB (%.2f GB available)", decimal_total, decimal_avl);
memory_info.append(buffer);
}
std::cout << memory_info << std::endl;
}
// ---- get harddisk info ---- //
std::string execCmd(const char *cmd)
{
char buffer[128] = { 0 };
std::string result;
FILE *pipe = _popen(cmd, "r");
if (!pipe) throw std::runtime_error("_popen() failed!");
while (!feof(pipe))
{
if (fgets(buffer, 128, pipe) != NULL)
result += buffer;
}
_pclose(pipe);
return result;
}
void getHardDiskInfo()
{
std::string hd_seiral = execCmd("wmic path win32_physicalmedia get SerialNumber");
std::cout << "HardDisk Serial Number: " << hd_seiral << std::endl;
}
// ---- get network info ---- //
void getNetworkInfo()
{
// PIP_ADAPTER_INFO struct contains network information
PIP_ADAPTER_INFO pIpAdapterInfo = new IP_ADAPTER_INFO();
unsigned long adapter_size = sizeof(IP_ADAPTER_INFO);
int ret = GetAdaptersInfo(pIpAdapterInfo, &adapter_size);
if (ret == ERROR_BUFFER_OVERFLOW)
{
// overflow, use the output size to recreate the handler
delete pIpAdapterInfo;
pIpAdapterInfo = (PIP_ADAPTER_INFO)new BYTE[adapter_size];
ret = GetAdaptersInfo(pIpAdapterInfo, &adapter_size);
}
if (ret == ERROR_SUCCESS)
{
int card_index = 0;
// may have many cards, it saved in linklist
while (pIpAdapterInfo)
{
std::cout << "---- " << "NetworkCard " << ++card_index << " ----" << std::endl;
std::cout << "Network Card Name: " << pIpAdapterInfo->AdapterName << std::endl;
std::cout << "Network Card Description: " << pIpAdapterInfo->Description << std::endl;
// get IP, one card may have many IPs
PIP_ADDR_STRING pIpAddr = &(pIpAdapterInfo->IpAddressList);
while (pIpAddr)
{
char local_ip[128] = { 0 };
strcpy(local_ip, pIpAddr->IpAddress.String);
std::cout << "Local IP: " << local_ip << std::endl;
pIpAddr = pIpAddr->Next;
}
char local_mac[128] = { 0 };
int char_index = 0;
for (int i = 0; i < pIpAdapterInfo->AddressLength; i++)
{
char temp_str[10] = { 0 };
sprintf(temp_str, "%02X-", pIpAdapterInfo->Address[i]); // X for uppercase, x for lowercase
strcpy(local_mac + char_index, temp_str);
char_index += 3;
}
local_mac[17] = '\0'; // remove tail '-'
std::cout << "Local Mac: " << local_mac << std::endl;
// here just need the first card info
break;
// iterate next
//pIpAdapterInfo = pIpAdapterInfo->Next;
}
}
if (pIpAdapterInfo)
delete pIpAdapterInfo;
}
// ---- get process info ---- //
void getProcessInfo()
{
int pid = GetCurrentProcessId();
// TODO: cpu and mem usage
printf("Current Pid: %d\n", pid);
}
int main(int argc, char *argv[])
{
std::cout << "=== os information ===" << std::endl;
getOsInfo();
std::cout << "=== cpu infomation ===" << std::endl;
getCpuInfo();
std::cout << "=== memory information ===" << std::endl;
getMemoryInfo();
std::cout << "=== harddisk information ===" << std::endl;
getHardDiskInfo();
std::cout << "=== network information ===" << std::endl;
getNetworkInfo();
printf("=== process information ===\n");
getProcessInfo();
return 0;
}
结果:
===os information===
os name: windows 10
os version: 6.2
===cpu infomation===
CPU main frequency: 2612MHz
CPU manufacture: GenuineIntel
CPU type: Intel(R) Core(TM) i5-3230M CPU @ 2.60GHz
===memory information===
total 7.86 GB (1.38 GB available)
=== harddisk information ===
HardDisk Serial Number: SerialNumber
0520B6776730A1F4
=== network information ===
---- NetworkCard 1 ----
Network Card Name: {403C08C9-5600-4BE9-8021-AAAADB63D678}
Network Card Description: Intel(R) Ethernet Connection (5) I219-LM
Local IP: 10.12.0.142
Local Mac: 50-9A-4C-14-B5-7F
=== process information ===
Current Pid: 2367
Linux
linux下很多信息都是存放着系统的/proc目录下,因此读文件就可以获取到了
代码:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
// mostly need to read the linux config files to get system info
// ---- get os info ---- //
void getOsInfo()
{
FILE *fp = fopen("/proc/version", "r");
if(NULL == fp)
printf("failed to open version\n");
char szTest[1000] = {0};
while(!feof(fp))
{
memset(szTest, 0, sizeof(szTest));
fgets(szTest, sizeof(szTest) - 1, fp); // leave out \n
printf("%s", szTest);
}
fclose(fp);
}
// ---- get cpu info ---- //
void getCpuInfo()
{
FILE *fp = fopen("/proc/cpuinfo", "r");
if(NULL == fp)
printf("failed to open cpuinfo\n");
char szTest[1000] = {0};
// read file line by line
while(!feof(fp))
{
memset(szTest, 0, sizeof(szTest));
fgets(szTest, sizeof(szTest) - 1, fp); // leave out \n
printf("%s", szTest);
}
fclose(fp);
}
// ---- get memory info ---- //
void getMemoryInfo()
{
FILE *fp = fopen("/proc/meminfo", "r");
if(NULL == fp)
printf("failed to open meminfo\n");
char szTest[1000] = {0};
while(!feof(fp))
{
memset(szTest, 0, sizeof(szTest));
fgets(szTest, sizeof(szTest) - 1, fp);
printf("%s", szTest);
}
fclose(fp);
}
// ---- get harddisk info ---- //
#include <fcntl.h>
#include <sys/ioctl.h>
#include <linux/hdreg.h>
void getHardDiskInfo()
{
// use cmd, this is the only way
static struct hd_driveid hd;
int fd;
if ((fd = open("/dev/sda", O_RDONLY | O_NONBLOCK)) < 0)
{
printf("ERROR opening /dev/sda\n");
return;
}
if (!ioctl(fd, HDIO_GET_IDENTITY, &hd))
{
printf("model ", hd.model);
printf("HardDisk Serial Number: %.20s\n", hd.serial_no);
}
else
printf("no available harddisk info");
}
// ---- get network info ---- //
#include <unistd.h>
#include <netdb.h>
#include <arpa/inet.h>
#include <ifaddrs.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <sys/ioctl.h>
#include <linux/if.h>
void getNetworkInfo()
{
// get hostname and external ip, simple and best way
char host_name[256] = {0};
gethostname(host_name, sizeof(host_name));
struct hostent* host = gethostbyname(host_name);
char ip_str[32] = {0};
const char* ret = inet_ntop(host->h_addrtype, host->h_addr_list[0], ip_str, sizeof(ip_str));
if (ret != NULL)
{
printf("Current HostName: %s\n", host_name);
printf("Current external IP: %s\n", ip_str);
}
// get multiple ip, works for linux
struct ifaddrs *ifAddrStruct = NULL;
struct ifaddrs *ifa = NULL;
getifaddrs(&ifAddrStruct);
for (ifa = ifAddrStruct; ifa != NULL; ifa = ifa->ifa_next)
{
if (!ifa->ifa_addr)
continue;
// check if IP4
if (ifa->ifa_addr->sa_family == AF_INET)
{
void *tmpAddrPtr = &((struct sockaddr_in *)ifa->ifa_addr)->sin_addr;
char local_ip[INET_ADDRSTRLEN];
inet_ntop(AF_INET, tmpAddrPtr, local_ip, INET_ADDRSTRLEN);
// actually only need external ip
printf("%s IP: %s\n", ifa->ifa_name, local_ip);
}
}
if (ifAddrStruct)
freeifaddrs(ifAddrStruct);
// get mac, need to create socket first, may not work for mac os
struct ifreq ifr;
int fd = socket(AF_INET, SOCK_DGRAM, 0);
char local_mac[128] = { 0 };
strcpy(ifr.ifr_name, "eth0"); // only need ethernet card
if (0 == ioctl(fd, SIOCGIFHWADDR, &ifr))
{
char temp_str[10] = { 0 };
memcpy(temp_str, ifr.ifr_hwaddr.sa_data, 6);
sprintf(local_mac, "%02x-%02x-%02x-%02x-%02x-%02x", temp_str[0]&0xff, temp_str[1]&0xff, temp_str[2]&0xff, temp_str[3]&0xff, temp_str[4]&0xff, temp_str[5]&0xff);
}
printf("Local Mac: %s\n", local_mac);
}
// ---- get process info ---- //
void getProcessInfo()
{
int pid = getpid();
// TODO: cpu and mem usage
printf("Current Pid: %d\n", pid);
}
int main(int argc, char **argv)
{
printf("=== os information ===\n");
getOsInfo();
printf("=== cpu infomation ===\n");
getCpuInfo();
printf("=== memory information ===\n");
getMemoryInfo();
printf("=== harddisk information ===\n");
getHardDiskInfo();
printf("=== network information ===\n");
getNetworkInfo();
printf("=== process information ===\n");
getProcessInfo();
return 0;
}
结果:
===os information===
Linux version 4.8.6-300.fc25.x86_64 (mockbuild@bkernel02.phx2.fedoraproject.org) (gcc version 6.2.1 20160916 (Red Hat 6.2.1-2) (GCC) ) #1 SMP Tue Nov 1 12:36:38 UTC 2016
===cpu infomation===
processor : 0
vendor_id : GenuineIntel
cpu family : 6
model : 58
model name : Intel(R) Core(TM) i5-3230M CPU @ 2.60GHz
stepping : 9
microcode : 0x1b
cpu MHz : 2599.755
cache size : 3072 KB
===memory information===
MemTotal: 3061552 kB
MemFree: 89584 kB
MemAvailable: 596876 kB
Buffers: 70372 kB
Cached: 707548 kB
SwapCached: 392 kB
=== harddisk information ===
HardDisk Serial Number: 0520B6776730A1F4
=== network information ===
Current HostName: tashaxing
Current external IP: 192.168.136.140
lo IP: 127.0.0.1
eth0 IP: 192.168.136.140
Local Mac: 00-0c-29-ec-7a-80
=== process information ===
Current Pid: 1152
PS:显卡参数可以用制造商提供的驱动API来取得