21 #if defined(__linux__)
22 # include <arpa/inet.h>
24 # include <linux/if.h>
25 # include <netinet/in.h>
27 # include <sys/ioctl.h>
28 # include <sys/socket.h>
29 # include <sys/statvfs.h>
30 # include <sys/types.h>
31 # include <sys/utsname.h>
34 extern char** environ;
36 #elif defined(__APPLE__)
37 # include <mach/mach.h>
40 # include <sys/mount.h>
41 # include <sys/param.h>
42 # include <sys/sysctl.h>
43 # include <sys/types.h>
62 # if (defined(WINVER)) && (WINVER >= 0x0502)
65 # pragma comment(lib, "pdh.lib")
66 # pragma comment(lib, "psapi.lib")
67 # pragma comment(lib, "wbemuuid.lib")
76 static void enableCpuLoadCollector();
77 static void disableCpuLoadCollector();
81 #if defined(__linux__)
86 size_t len = strlen(tag);
87 while (bufptr !=
nullptr) {
88 if (*bufptr ==
'\n') {
91 if (strncmp(tag, bufptr, len) == 0) {
92 retval = strtol(bufptr + len, &tail, 10);
93 if (tail == bufptr + len) {
98 bufptr = strchr(bufptr,
'\n');
104 bool getCpuEntry(
const char* tag,
const char* buff, std::string& value)
106 if (strlen(buff) <= strlen(tag)) {
110 if (strncmp(buff, tag, strlen(tag)) != 0) {
114 const char* pos1 = strchr(buff,
':');
115 if (pos1 ==
nullptr) {
119 while ((*pos1 !=
'\0') && ((*pos1 ==
' ') || (*pos1 ==
':') || (*pos1 ==
'\t'))) {
122 const char* pos2 = buff + strlen(buff) - 1;
123 while ((*pos2 !=
':') && ((*pos2 ==
' ') || (*pos2 ==
'\n'))) {
129 value = std::string(pos1, pos2 - pos1 + 1);
145 load.cpuLoad15 = 0.0;
146 load.cpuLoadInstant = (int)0;
156 load.cpuLoadInstant = (int)phdCpuLoad();
157 samples.push_back(load.cpuLoadInstant);
161 std::vector<int>::reverse_iterator rti;
169 load.cpuLoad1 = (double)(sum / n) / 100.0;
172 load.cpuLoad5 = (double)(sum / n) / 100.0;
174 load.cpuLoad15 = (double)(sum / n) / 100.0;
190 # if (defined(WINVER)) && (WINVER >= 0x0502)
195 phdStatus = PdhOpenQuery(
nullptr, 0, &hPhdQuery);
196 if (phdStatus != ERROR_SUCCESS)
199 PdhAddCounter(hPhdQuery, TEXT(
"\\Processor(_Total)\\% Processor Time"), 0, &phdCounter);
200 PdhCollectQueryData(hPhdQuery);
205 phdStatus = PdhCollectQueryData(hPhdQuery);
206 if (phdStatus != ERROR_SUCCESS)
208 phdStatus = PdhGetFormattedCounterValue(phdCounter,
209 PDH_FMT_DOUBLE | PDH_FMT_NOCAP100,
212 if (phdStatus != ERROR_SUCCESS)
214 return phdFmtValue.doubleValue;
224 # if (defined(WINVER)) && (WINVER >= 0x0502)
225 PDH_STATUS phdStatus;
227 PDH_FMT_COUNTERVALUE phdFmtValue;
236 static CpuLoadCollector* globalLoadCollector =
nullptr;
238 void enableCpuLoadCollector()
240 if (globalLoadCollector ==
nullptr) {
241 globalLoadCollector =
new CpuLoadCollector();
242 globalLoadCollector->start();
246 void disableCpuLoadCollector()
248 if (globalLoadCollector) {
249 globalLoadCollector->stop();
250 delete globalLoadCollector;
251 globalLoadCollector =
nullptr;
265 MEMORYSTATUSEX statex;
266 statex.dwLength =
sizeof(statex);
267 if (GlobalMemoryStatusEx(&statex)) {
273 #if defined(__linux__)
275 FILE* procmem = fopen(
"/proc/meminfo",
"r");
276 if (procmem !=
nullptr) {
277 while (fgets(
buffer, 128, procmem) !=
nullptr) {
279 if ((
ret = getMemEntry(
"MemTotal:",
buffer)) > 0) {
283 if ((
ret = getMemEntry(
"MemFree:",
buffer)) > 0) {
289 #elif defined(__APPLE__)
292 mach_port_t mach_port;
293 mach_msg_type_number_t count;
294 vm_statistics64_data_t vm_stats;
296 mach_port = mach_host_self();
297 count = HOST_VM_INFO64_COUNT;
298 if (KERN_SUCCESS == host_page_size(mach_port, &page_size) && KERN_SUCCESS == host_statistics64(mach_port, HOST_VM_INFO, (host_info64_t)&vm_stats, &count)) {
300 natural_t activePages = vm_stats.active_count + vm_stats.wire_count;
301 natural_t inactivePages = vm_stats.inactive_count + vm_stats.free_count;
302 natural_t totalPages = activePages + inactivePages;
304 int64_t total = totalPages * page_size;
305 int64_t freeSpace = inactivePages * page_size;
326 DWORD dwSectorsPerCluster = 0, dwBytesPerSector = 0;
327 DWORD dwFreeClusters = 0, dwTotalClusters = 0;
331 if (GetDiskFreeSpaceA(strHome.c_str(), &dwSectorsPerCluster, &dwBytesPerSector, &dwFreeClusters, &dwTotalClusters)) {
332 storage.
freeSpace = (
capacity_t)((dwFreeClusters / 1048576.0) * dwSectorsPerCluster * dwBytesPerSector);
333 storage.
totalSpace = (
capacity_t)((dwTotalClusters) / 1048576.0 * dwSectorsPerCluster * dwBytesPerSector);
337 #if defined(__linux__)
339 if (strHome.empty()) {
344 if (statvfs(strHome.c_str(), &vfs) == 0) {
345 storage.
totalSpace = (int)(vfs.f_blocks * vfs.f_bsize / (1048576));
346 storage.
freeSpace = (int)(vfs.f_bavail * vfs.f_bsize / (1048576));
351 #if defined(__APPLE__)
357 if (statfs(strHome.c_str(), &vfs) == 0) {
358 storage.
totalSpace = (int)(vfs.f_blocks * vfs.f_bsize / (1048576));
359 storage.
freeSpace = (int)(vfs.f_bavail * vfs.f_bsize / (1048576));
462 GetSystemInfo(&sysinf);
463 switch (sysinf.wProcessorArchitecture) {
464 case PROCESSOR_ARCHITECTURE_AMD64: {
468 case PROCESSOR_ARCHITECTURE_IA64: {
472 case PROCESSOR_ARCHITECTURE_INTEL: {
479 processor.
siblings = sysinf.dwNumberOfProcessors;
481 switch (sysinf.dwProcessorType) {
482 case PROCESSOR_INTEL_386: {
483 processor.
model =
"PROCESSOR_INTEL_386";
486 case PROCESSOR_INTEL_486: {
487 processor.
model =
"PROCESSOR_INTEL_486";
490 case PROCESSOR_INTEL_PENTIUM: {
491 processor.
model =
"PROCESSOR_INTEL_PENTIUM";
494 case PROCESSOR_INTEL_IA64: {
495 processor.
model =
"PROCESSOR_INTEL_IA64";
498 case PROCESSOR_AMD_X8664: {
499 processor.
model =
"PROCESSOR_AMD_X8664";
505 DWORD BufSize =
sizeof(DWORD);
507 if (RegOpenKeyEx(HKEY_LOCAL_MACHINE,
508 "HARDWARE\\DESCRIPTION\\System\\CentralProcessor\\0",
513 RegQueryValueEx(hKey,
"~MHz",
nullptr,
nullptr, (LPBYTE)&dwMHz, &BufSize);
523 #if defined(__linux__)
525 FILE* proccpu = fopen(
"/proc/cpuinfo",
"r");
526 if (proccpu !=
nullptr) {
527 while (fgets(
buffer, 128, proccpu) !=
nullptr) {
529 if (getCpuEntry(
"model",
buffer, value) && !getCpuEntry(
"model name",
buffer, value)) {
532 if (getCpuEntry(
"model name",
buffer, value)) {
533 processor.
model = value;
535 if (getCpuEntry(
"vendor_id",
buffer, value)) {
538 if (getCpuEntry(
"cpu family",
buffer, value)) {
539 processor.
family = atoi(value.c_str());
541 if (getCpuEntry(
"cpu cores",
buffer, value)) {
542 processor.
cores = atoi(value.c_str());
544 if (getCpuEntry(
"siblings",
buffer, value)) {
545 processor.
siblings = atoi(value.c_str());
547 if (getCpuEntry(
"cpu MHz",
buffer, value)) {
548 processor.
frequency = atof(value.c_str());
555 if (uname(&uts) == 0) {
558 #elif defined(__APPLE__)
561 int mib[] = {CTL_HW, HW_CPU_FREQ};
563 size_t length =
sizeof(value);
565 if (!sysctl(mib, 2, &value, &length,
nullptr, 0)) {
569 if (!sysctlbyname(
"hw.logicalcpu", &value, &length,
nullptr, 0)) {
570 processor.
cores = value;
575 size_t buffLen = 512;
576 if (!sysctlbyname(
"machdep.cpu.vendor", buff, &buffLen,
nullptr, 0)) {
581 if (!sysctlbyname(
"machdep.cpu.brand_string", buff, &buffLen,
nullptr, 0)) {
582 processor.
model = buff;
585 if (!sysctlbyname(
"machdep.cpu.family", &value, &length,
nullptr, 0)) {
589 if (!sysctlbyname(
"machdep.cpu.model", &value, &length,
nullptr, 0)) {
605 platform.
name =
"Windows";
606 OSVERSIONINFOEX osver;
607 osver.dwOSVersionInfoSize =
sizeof(osver);
608 if (GetVersionEx((LPOSVERSIONINFO)&osver)) {
610 sprintf(buff,
"%d.%d", osver.dwMajorVersion, osver.dwMinorVersion);
613 if ((osver.dwMajorVersion == 10) && (osver.dwMinorVersion == 0) && (osver.wProductType == VER_NT_WORKSTATION)) {
615 }
else if ((osver.dwMajorVersion == 10) && (osver.dwMinorVersion == 0) && (osver.wProductType != VER_NT_WORKSTATION)) {
617 }
else if ((osver.dwMajorVersion == 6) && (osver.dwMinorVersion == 2) && (osver.wProductType == VER_NT_WORKSTATION)) {
619 }
else if ((osver.dwMajorVersion == 6) && (osver.dwMinorVersion == 3) && (osver.wProductType != VER_NT_WORKSTATION)) {
621 }
else if ((osver.dwMajorVersion == 6) && (osver.dwMinorVersion == 2) && (osver.wProductType == VER_NT_WORKSTATION)) {
623 }
else if ((osver.dwMajorVersion == 6) && (osver.dwMinorVersion == 2) && (osver.wProductType != VER_NT_WORKSTATION)) {
625 }
else if ((osver.dwMajorVersion == 6) && (osver.dwMinorVersion == 1) && (osver.wProductType == VER_NT_WORKSTATION)) {
627 }
else if ((osver.dwMajorVersion == 6) && (osver.dwMinorVersion == 1) && (osver.wProductType != VER_NT_WORKSTATION)) {
629 }
else if ((osver.dwMajorVersion == 6) && (osver.dwMinorVersion == 0) && (osver.wProductType == VER_NT_WORKSTATION)) {
631 }
else if ((osver.dwMajorVersion == 6) && (osver.dwMinorVersion == 0) && (osver.wProductType != VER_NT_WORKSTATION)) {
633 }
else if ((osver.dwMajorVersion == 5) && (osver.dwMinorVersion == 2)) {
639 }
else if ((osver.dwMajorVersion == 5) && (osver.dwMinorVersion == 2) && (osver.wProductType == VER_NT_WORKSTATION)) {
641 }
else if ((osver.dwMajorVersion == 5) && (osver.dwMinorVersion == 1)) {
643 }
else if ((osver.dwMajorVersion == 5) && (osver.dwMinorVersion == 0)) {
648 const char* a = GetEnvironmentStrings();
650 for (
size_t i = 0;; i++) {
652 std::string tmpVariable(a + prev, a + i);
653 size_t equalsSign = tmpVariable.find(
"=");
654 if (equalsSign != std::string::npos && equalsSign != 0)
656 platform.
environmentVars.
put(tmpVariable.substr(0, equalsSign), tmpVariable.substr(equalsSign + 1));
659 if (a[i + 1] ==
'\0') {
667 #if defined(__linux__)
669 if (uname(&uts) == 0) {
670 platform.
name = uts.sysname;
671 platform.
kernel = uts.release;
673 platform.
name =
"Linux";
677 FILE* release = popen(
"lsb_release -ric",
"r");
678 if (release !=
nullptr) {
679 while (fgets(
buffer, 128, release) !=
nullptr) {
681 if (getCpuEntry(
"Distributor ID",
buffer, value)) {
684 if (getCpuEntry(
"Release",
buffer, value)) {
687 if (getCpuEntry(
"Codename",
buffer, value)) {
694 char* varChar = *environ;
696 for (
int i = 0; varChar !=
nullptr; i++) {
697 std::string tmpVariable(varChar);
698 size_t equalsSign = tmpVariable.find(
'=');
699 if (equalsSign != std::string::npos) {
700 platform.
environmentVars.
put(tmpVariable.substr(0, equalsSign), tmpVariable.substr(equalsSign + 1));
702 varChar = *(environ + i);
706 #if defined(__APPLE__)
709 size_t buffLen = 512;
710 if (!sysctlbyname(
"kern.ostype", buff, &buffLen,
nullptr, 0)) {
711 platform.
name = buff;
714 if (!sysctlbyname(
"kern.osrelease", buff, &buffLen,
nullptr, 0)) {
729 char path[MAX_PATH + 1];
730 if (SHGetFolderPathA(
nullptr, CSIDL_PROFILE,
nullptr, 0, path) == S_OK)
733 char username[UNLEN + 1];
734 DWORD nsize = UNLEN + 1;
735 if (GetUserName(username, &nsize)) {
741 #if defined(__linux__) || defined(__APPLE__)
742 struct passwd* pwd = getpwuid(getuid());
744 if (pwd !=
nullptr) {
763 if (globalLoadCollector) {
764 load = globalLoadCollector->getCpuLoad();
774 #if defined(__linux__)
775 FILE* procload = fopen(
"/proc/loadavg",
"r");
776 if (procload !=
nullptr) {
780 char* tail = strchr(buff,
'/');
781 if ((tail !=
nullptr) && (tail != buff)) {
789 #if defined(__APPLE__)
791 mach_msg_type_number_t count = HOST_CPU_LOAD_INFO_COUNT;
792 host_cpu_load_info_data_t cpu_load;
794 if (KERN_SUCCESS == host_statistics(mach_host_self(), HOST_CPU_LOAD_INFO, (host_info64_t)&cpu_load, &count)) {
797 for (
int i = 0; i < CPU_STATE_MAX; ++i) {
798 total += cpu_load.cpu_ticks[i];
801 load.
cpuLoad1 = 100.0 * cpu_load.cpu_ticks[CPU_STATE_USER] / total;
819 #if defined(__linux__)
821 char cmdline[256] = {0};
823 sprintf(filename,
"/proc/%d/cmdline", pid);
824 file = fopen(filename,
"r");
825 if (file !=
nullptr) {
826 char* p = fgets(cmdline,
sizeof(cmdline) /
sizeof(*cmdline), file);
839 size_t index = info.
name.find(
' ');
840 if (index != std::string::npos) {
841 info.
name = info.
name.substr(0, index);
849 struct sched_param param;
850 if (sched_getparam(pid, ¶m) == 0) {
855 #elif defined(_WIN32)
856 HANDLE hnd = OpenProcess(PROCESS_QUERY_INFORMATION | PROCESS_VM_READ, FALSE, pid);
858 TCHAR filename[MAX_PATH];
859 if (GetModuleBaseName(hnd, 0, filename, MAX_PATH)) {
860 info.
name = filename;
867 IWbemLocator* WbemLocator =
nullptr;
868 IWbemServices* WbemServices =
nullptr;
869 IEnumWbemClassObject* EnumWbem =
nullptr;
872 hr = CoInitializeEx(0, COINIT_MULTITHREADED);
873 hr = CoInitializeSecurity(
nullptr, -1,
nullptr,
nullptr, RPC_C_AUTHN_LEVEL_DEFAULT, RPC_C_IMP_LEVEL_IMPERSONATE,
nullptr, EOAC_NONE,
nullptr);
874 hr = CoCreateInstance(CLSID_WbemLocator, 0, CLSCTX_INPROC_SERVER, IID_IWbemLocator, (LPVOID*)&WbemLocator);
875 if (WbemLocator !=
nullptr) {
877 hr = WbemLocator->ConnectServer(L
"ROOT\\CIMV2",
nullptr,
nullptr, 0, 0, 0, 0, &WbemServices);
878 if (WbemServices !=
nullptr) {
880 hr = WbemServices->ExecQuery(L
"WQL", L
"SELECT ProcessId, CommandLine FROM Win32_Process", WBEM_FLAG_FORWARD_ONLY,
nullptr, &EnumWbem);
882 if (EnumWbem !=
nullptr) {
883 IWbemClassObject* result =
nullptr;
884 ULONG returnedCount = 0;
886 while ((hr = EnumWbem->Next(WBEM_INFINITE, 1, &result, &returnedCount)) == S_OK) {
891 hr = result->Get(L
"ProcessId", 0, &ProcessId, 0, 0);
892 hr = result->Get(L
"CommandLine", 0, &CommandLine, 0, 0);
893 if (!(CommandLine.vt == VT_NULL) && ProcessId.uintVal == (
unsigned int)pid) {
895 int res = WideCharToMultiByte(CP_UTF8, 0, CommandLine.bstrVal, -1,
nullptr, 0,
nullptr,
nullptr);
897 WideCharToMultiByte(CP_UTF8, 0, CommandLine.bstrVal, -1, &info.
arguments[0], res,
nullptr,
nullptr);
905 VariantClear(&ProcessId);
906 VariantClear(&CommandLine);
915 WbemServices->Release();
918 WbemLocator->Release();
922 #elif defined(__APPLE__)
924 size_t length =
sizeof(procInfo);
926 int mib[4] = {CTL_KERN, KERN_PROC, KERN_PROC_PID, pid};
928 if (!sysctl(mib, 4, &procInfo, &length,
nullptr, 0)) {
929 info.
name = procInfo.kp_proc.p_comm;
930 info.
pid = procInfo.kp_proc.p_pid;
933 mib[1] = KERN_PROCARGS;
938 int result = sysctl(mib, 3,
nullptr, &argv_len,
nullptr, 0);
940 yCError(SYSTEMINFO,
"sysctl: %d, %s", errno, strerror(errno));
945 proc_argv = (
char*)malloc(
sizeof(
char) * argv_len);
946 result = sysctl(mib, 3, proc_argv, &argv_len,
nullptr, 0);
948 yCError(SYSTEMINFO,
"sysctl: %d, %s", errno, strerror(errno));
956 while (index < argv_len && proc_argv[index] !=
'\0') {
965 std::stringstream arguments;
966 while (index < argv_len) {
967 if (proc_argv[index] ==
'\0' && index != argv_len - 1) {
970 arguments << proc_argv[index];
An abstraction for a periodic thread.
void put(const std::string &key, const std::string &value)
Associate the given key with the given string.
A class for thread synchronization and mutual exclusion.
static MemoryInfo getMemoryInfo()
getMemoryInfo
static ProcessInfo getProcessInfo(int pid=0)
gets the operating system process information given by its PID.
static PlatformInfo getPlatformInfo()
getPlatformInfo
static UserInfo getUserInfo()
getUserInfo
static LoadInfo getLoadInfo()
getLoadInfo
static StorageInfo getStorageInfo()
getStorageInfo
static ProcessorInfo getProcessorInfo()
getProcessorInfo
#define yCError(component,...)
#define YARP_OS_LOG_COMPONENT(name, name_string)
An interface to the operating system, including Port based communication.
int getpid()
Portable wrapper for the getppid() function.
The LoadInfo struct holds the current cpu load information.
The MemoryInfo struct holds the system memory information.
The ProcessInfo struct provides the operating system process information.
The ProcessorInfo struct holds the processor information.
The StorageInfo struct holds the system storage information.
The UserInfo struct holds the current user information.