C/C++获取系统,CPU,内存,硬盘,IP和MAC(windows和linux)

Home / C++ 百晓生 2019-3-18 1625

有时候需要在工程里面获取一些系统或者硬件的信息,比如系统版本,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;
}
 
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();
 
	system("pause");
	return 0;
}

=== os information ===

os name: windows 10

os version: 6.2

=== cpu infomation ===

CPU manufacture: GenuineIntel

CPU type: Intel(R) Core(TM) i7-8700 CPU @ 3.20GHz

CPU main frequency: 3231MHz

=== memory information ===

total 7.92 GB (4.00 GB available)

=== harddisk information ===

HardDisk Serial Number: SerialNumber

0100_0000_0000_0000.

W9A5EXTF

NA8QC8GM

=== network information ===

---- NetworkCard 1 ----

Network Card Name: {50C5A628-46B0-4009-9200-5CE1FD512B2B}

Network Card Description: Realtek PCIe GBE Family Controller

Local IP: 192.168.3.2

Local Mac: 0C-9D-92-1A-DE-A6

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 <ifaddrs.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <sys/ioctl.h>
#include <linux/if.h>
void getNetworkInfo()
{
    // get ip, works for linux and mac os, best method
    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);
 
}
 
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();
 
    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 ===

lo IP: 127.0.0.1

eth0 IP: 192.168.136.140

Local Mac: 00-0c-29-ec-7a-80

--------------------- 

本文链接:https://www.it72.com/12516.htm

推荐阅读
最新回复 (0)
返回