19# include <arpa/inet.h>
22# include <netinet/in.h>
24# include <sys/ioctl.h>
25# include <sys/socket.h>
26# include <sys/statvfs.h>
27# include <sys/types.h>
28# include <sys/utsname.h>
33#elif defined(__APPLE__)
34# include <mach/mach.h>
37# include <sys/mount.h>
38# include <sys/param.h>
39# include <sys/sysctl.h>
40# include <sys/types.h>
59# if (defined(WINVER)) && (WINVER >= 0x0502)
62# pragma comment(lib, "pdh.lib")
63# pragma comment(lib, "psapi.lib")
64# pragma comment(lib, "wbemuuid.lib")
73static void enableCpuLoadCollector();
74static void disableCpuLoadCollector();
83 size_t len = strlen(tag);
84 while (bufptr !=
nullptr) {
85 if (*bufptr ==
'\n') {
88 if (strncmp(tag, bufptr, len) == 0) {
89 retval = strtol(bufptr + len, &tail, 10);
90 if (tail == bufptr + len) {
95 bufptr = strchr(bufptr,
'\n');
101bool getCpuEntry(
const char* tag,
const char* buff, std::string& value)
103 if (strlen(buff) <= strlen(tag)) {
107 if (strncmp(buff, tag, strlen(tag)) != 0) {
111 const char* pos1 = strchr(buff,
':');
112 if (pos1 ==
nullptr) {
116 while ((*pos1 !=
'\0') && ((*pos1 ==
' ') || (*pos1 ==
':') || (*pos1 ==
'\t'))) {
119 const char* pos2 = buff + strlen(buff) - 1;
120 while ((*pos2 !=
':') && ((*pos2 ==
' ') || (*pos2 ==
'\n'))) {
126 value = std::string(pos1, pos2 - pos1 + 1);
142 load.cpuLoad15 = 0.0;
143 load.cpuLoadInstant = (int)0;
153 load.cpuLoadInstant = (int)phdCpuLoad();
154 samples.push_back(load.cpuLoadInstant);
158 std::vector<int>::reverse_iterator rti;
166 load.cpuLoad1 = (double)(sum / n) / 100.0;
169 load.cpuLoad5 = (double)(sum / n) / 100.0;
171 load.cpuLoad15 = (double)(sum / n) / 100.0;
187# if (defined(WINVER)) && (WINVER >= 0x0502)
192 phdStatus = PdhOpenQuery(
nullptr, 0, &hPhdQuery);
193 if (phdStatus != ERROR_SUCCESS)
196 PdhAddCounter(hPhdQuery, TEXT(
"\\Processor(_Total)\\% Processor Time"), 0, &phdCounter);
197 PdhCollectQueryData(hPhdQuery);
202 phdStatus = PdhCollectQueryData(hPhdQuery);
203 if (phdStatus != ERROR_SUCCESS)
205 phdStatus = PdhGetFormattedCounterValue(phdCounter,
206 PDH_FMT_DOUBLE | PDH_FMT_NOCAP100,
209 if (phdStatus != ERROR_SUCCESS)
211 return phdFmtValue.doubleValue;
221# if (defined(WINVER)) && (WINVER >= 0x0502)
222 PDH_STATUS phdStatus;
224 PDH_FMT_COUNTERVALUE phdFmtValue;
233static CpuLoadCollector* globalLoadCollector =
nullptr;
235void enableCpuLoadCollector()
237 if (globalLoadCollector ==
nullptr) {
238 globalLoadCollector =
new CpuLoadCollector();
239 globalLoadCollector->start();
243void disableCpuLoadCollector()
245 if (globalLoadCollector) {
246 globalLoadCollector->stop();
247 delete globalLoadCollector;
248 globalLoadCollector =
nullptr;
262 MEMORYSTATUSEX statex;
263 statex.dwLength =
sizeof(statex);
264 if (GlobalMemoryStatusEx(&statex)) {
270#if defined(__linux__)
272 FILE* procmem = fopen(
"/proc/meminfo",
"r");
273 if (procmem !=
nullptr) {
274 while (fgets(
buffer, 128, procmem) !=
nullptr) {
276 if ((
ret = getMemEntry(
"MemTotal:",
buffer)) > 0) {
280 if ((
ret = getMemEntry(
"MemFree:",
buffer)) > 0) {
286#elif defined(__APPLE__)
289 mach_port_t mach_port;
290 mach_msg_type_number_t count;
291 vm_statistics64_data_t vm_stats;
293 mach_port = mach_host_self();
294 count = HOST_VM_INFO64_COUNT;
295 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)) {
297 natural_t activePages = vm_stats.active_count + vm_stats.wire_count;
298 natural_t inactivePages = vm_stats.inactive_count + vm_stats.free_count;
299 natural_t totalPages = activePages + inactivePages;
301 int64_t total = totalPages * page_size;
302 int64_t freeSpace = inactivePages * page_size;
323 DWORD dwSectorsPerCluster = 0, dwBytesPerSector = 0;
324 DWORD dwFreeClusters = 0, dwTotalClusters = 0;
328 if (GetDiskFreeSpaceA(strHome.c_str(), &dwSectorsPerCluster, &dwBytesPerSector, &dwFreeClusters, &dwTotalClusters)) {
329 storage.
freeSpace = (
capacity_t)((dwFreeClusters / 1048576.0) * dwSectorsPerCluster * dwBytesPerSector);
330 storage.
totalSpace = (
capacity_t)((dwTotalClusters) / 1048576.0 * dwSectorsPerCluster * dwBytesPerSector);
334#if defined(__linux__)
336 if (strHome.empty()) {
341 if (statvfs(strHome.c_str(), &vfs) == 0) {
342 storage.
totalSpace = (int)(vfs.f_blocks * vfs.f_bsize / (1048576));
343 storage.
freeSpace = (int)(vfs.f_bavail * vfs.f_bsize / (1048576));
348#if defined(__APPLE__)
354 if (statfs(strHome.c_str(), &vfs) == 0) {
355 storage.
totalSpace = (int)(vfs.f_blocks * vfs.f_bsize / (1048576));
356 storage.
freeSpace = (int)(vfs.f_bavail * vfs.f_bsize / (1048576));
459 GetSystemInfo(&sysinf);
460 switch (sysinf.wProcessorArchitecture) {
461 case PROCESSOR_ARCHITECTURE_AMD64: {
465 case PROCESSOR_ARCHITECTURE_IA64: {
469 case PROCESSOR_ARCHITECTURE_INTEL: {
476 processor.
siblings = sysinf.dwNumberOfProcessors;
478 switch (sysinf.dwProcessorType) {
479 case PROCESSOR_INTEL_386: {
480 processor.
model =
"PROCESSOR_INTEL_386";
483 case PROCESSOR_INTEL_486: {
484 processor.
model =
"PROCESSOR_INTEL_486";
487 case PROCESSOR_INTEL_PENTIUM: {
488 processor.
model =
"PROCESSOR_INTEL_PENTIUM";
491 case PROCESSOR_INTEL_IA64: {
492 processor.
model =
"PROCESSOR_INTEL_IA64";
495 case PROCESSOR_AMD_X8664: {
496 processor.
model =
"PROCESSOR_AMD_X8664";
502 DWORD BufSize =
sizeof(DWORD);
504 if (RegOpenKeyEx(HKEY_LOCAL_MACHINE,
505 "HARDWARE\\DESCRIPTION\\System\\CentralProcessor\\0",
510 RegQueryValueEx(hKey,
"~MHz",
nullptr,
nullptr, (LPBYTE)&dwMHz, &BufSize);
520#if defined(__linux__)
522 FILE* proccpu = fopen(
"/proc/cpuinfo",
"r");
523 if (proccpu !=
nullptr) {
524 while (fgets(
buffer, 128, proccpu) !=
nullptr) {
526 if (getCpuEntry(
"model",
buffer, value) && !getCpuEntry(
"model name",
buffer, value)) {
529 if (getCpuEntry(
"model name",
buffer, value)) {
530 processor.
model = value;
532 if (getCpuEntry(
"vendor_id",
buffer, value)) {
535 if (getCpuEntry(
"cpu family",
buffer, value)) {
536 processor.
family = atoi(value.c_str());
538 if (getCpuEntry(
"cpu cores",
buffer, value)) {
539 processor.
cores = atoi(value.c_str());
541 if (getCpuEntry(
"siblings",
buffer, value)) {
542 processor.
siblings = atoi(value.c_str());
544 if (getCpuEntry(
"cpu MHz",
buffer, value)) {
545 processor.
frequency = atof(value.c_str());
552 if (uname(&uts) == 0) {
555#elif defined(__APPLE__)
558 int mib[] = {CTL_HW, HW_CPU_FREQ};
560 size_t length =
sizeof(value);
562 if (!sysctl(mib, 2, &value, &length,
nullptr, 0)) {
566 if (!sysctlbyname(
"hw.logicalcpu", &value, &length,
nullptr, 0)) {
567 processor.
cores = value;
572 size_t buffLen = 512;
573 if (!sysctlbyname(
"machdep.cpu.vendor", buff, &buffLen,
nullptr, 0)) {
578 if (!sysctlbyname(
"machdep.cpu.brand_string", buff, &buffLen,
nullptr, 0)) {
579 processor.
model = buff;
582 if (!sysctlbyname(
"machdep.cpu.family", &value, &length,
nullptr, 0)) {
586 if (!sysctlbyname(
"machdep.cpu.model", &value, &length,
nullptr, 0)) {
602 platform.
name =
"Windows";
603 OSVERSIONINFOEX osver;
604 osver.dwOSVersionInfoSize =
sizeof(osver);
605 if (GetVersionEx((LPOSVERSIONINFO)&osver)) {
607 sprintf(buff,
"%d.%d", osver.dwMajorVersion, osver.dwMinorVersion);
610 if ((osver.dwMajorVersion == 10) && (osver.dwMinorVersion == 0) && (osver.wProductType == VER_NT_WORKSTATION)) {
612 }
else if ((osver.dwMajorVersion == 10) && (osver.dwMinorVersion == 0) && (osver.wProductType != VER_NT_WORKSTATION)) {
614 }
else if ((osver.dwMajorVersion == 6) && (osver.dwMinorVersion == 2) && (osver.wProductType == VER_NT_WORKSTATION)) {
616 }
else if ((osver.dwMajorVersion == 6) && (osver.dwMinorVersion == 3) && (osver.wProductType != VER_NT_WORKSTATION)) {
618 }
else if ((osver.dwMajorVersion == 6) && (osver.dwMinorVersion == 2) && (osver.wProductType == VER_NT_WORKSTATION)) {
620 }
else if ((osver.dwMajorVersion == 6) && (osver.dwMinorVersion == 2) && (osver.wProductType != VER_NT_WORKSTATION)) {
622 }
else if ((osver.dwMajorVersion == 6) && (osver.dwMinorVersion == 1) && (osver.wProductType == VER_NT_WORKSTATION)) {
624 }
else if ((osver.dwMajorVersion == 6) && (osver.dwMinorVersion == 1) && (osver.wProductType != VER_NT_WORKSTATION)) {
626 }
else if ((osver.dwMajorVersion == 6) && (osver.dwMinorVersion == 0) && (osver.wProductType == VER_NT_WORKSTATION)) {
628 }
else if ((osver.dwMajorVersion == 6) && (osver.dwMinorVersion == 0) && (osver.wProductType != VER_NT_WORKSTATION)) {
630 }
else if ((osver.dwMajorVersion == 5) && (osver.dwMinorVersion == 2)) {
636 }
else if ((osver.dwMajorVersion == 5) && (osver.dwMinorVersion == 2) && (osver.wProductType == VER_NT_WORKSTATION)) {
638 }
else if ((osver.dwMajorVersion == 5) && (osver.dwMinorVersion == 1)) {
640 }
else if ((osver.dwMajorVersion == 5) && (osver.dwMinorVersion == 0)) {
645 const char* a = GetEnvironmentStrings();
647 for (
size_t i = 0;; i++) {
649 std::string tmpVariable(a + prev, a + i);
650 size_t equalsSign = tmpVariable.find(
"=");
651 if (equalsSign != std::string::npos && equalsSign != 0)
653 platform.
environmentVars.
put(tmpVariable.substr(0, equalsSign), tmpVariable.substr(equalsSign + 1));
656 if (a[i + 1] ==
'\0') {
664#if defined(__linux__)
666 if (uname(&uts) == 0) {
667 platform.
name = uts.sysname;
668 platform.
kernel = uts.release;
670 platform.
name =
"Linux";
674 FILE* release = popen(
"lsb_release -ric",
"r");
675 if (release !=
nullptr) {
676 while (fgets(
buffer, 128, release) !=
nullptr) {
678 if (getCpuEntry(
"Distributor ID",
buffer, value)) {
681 if (getCpuEntry(
"Release",
buffer, value)) {
684 if (getCpuEntry(
"Codename",
buffer, value)) {
691 char* varChar = *environ;
693 for (
int i = 0; varChar !=
nullptr; i++) {
694 std::string tmpVariable(varChar);
695 size_t equalsSign = tmpVariable.find(
'=');
696 if (equalsSign != std::string::npos) {
697 platform.
environmentVars.
put(tmpVariable.substr(0, equalsSign), tmpVariable.substr(equalsSign + 1));
699 varChar = *(environ + i);
703#if defined(__APPLE__)
706 size_t buffLen = 512;
707 if (!sysctlbyname(
"kern.ostype", buff, &buffLen,
nullptr, 0)) {
708 platform.
name = buff;
711 if (!sysctlbyname(
"kern.osrelease", buff, &buffLen,
nullptr, 0)) {
726 char path[MAX_PATH + 1];
727 if (SHGetFolderPathA(
nullptr, CSIDL_PROFILE,
nullptr, 0, path) == S_OK)
730 char username[UNLEN + 1];
731 DWORD nsize = UNLEN + 1;
732 if (GetUserName(username, &nsize)) {
738#if defined(__linux__) || defined(__APPLE__)
739 struct passwd* pwd = getpwuid(getuid());
741 if (pwd !=
nullptr) {
760 if (globalLoadCollector) {
761 load = globalLoadCollector->getCpuLoad();
771#if defined(__linux__)
772 FILE* procload = fopen(
"/proc/loadavg",
"r");
773 if (procload !=
nullptr) {
777 char* tail = strchr(buff,
'/');
778 if ((tail !=
nullptr) && (tail != buff)) {
786#if defined(__APPLE__)
788 mach_msg_type_number_t count = HOST_CPU_LOAD_INFO_COUNT;
789 host_cpu_load_info_data_t cpu_load;
791 if (KERN_SUCCESS == host_statistics(mach_host_self(), HOST_CPU_LOAD_INFO, (host_info64_t)&cpu_load, &count)) {
794 for (
int i = 0; i < CPU_STATE_MAX; ++i) {
795 total += cpu_load.cpu_ticks[i];
798 load.
cpuLoad1 = 100.0 * cpu_load.cpu_ticks[CPU_STATE_USER] / total;
814 info.schedPolicy = -1;
815 info.schedPriority = -1;
816#if defined(__linux__)
818 char cmdline[256] = {0};
820 sprintf(filename,
"/proc/%d/cmdline", pid);
821 file = fopen(filename,
"r");
822 if (file !=
nullptr) {
823 char* p = fgets(cmdline,
sizeof(cmdline) /
sizeof(*cmdline), file);
836 size_t index =
info.name.find(
' ');
837 if (index != std::string::npos) {
838 info.name =
info.name.substr(0, index);
839 info.arguments = cmdline;
840 info.arguments =
info.arguments.substr(index + 1);
846 struct sched_param param;
847 if (sched_getparam(pid, ¶m) == 0) {
848 info.schedPriority = param.__sched_priority;
850 info.schedPolicy = sched_getscheduler(pid);
853 HANDLE hnd = OpenProcess(PROCESS_QUERY_INFORMATION | PROCESS_VM_READ, FALSE, pid);
855 TCHAR filename[MAX_PATH];
856 if (GetModuleBaseName(hnd, 0, filename, MAX_PATH)) {
857 info.name = filename;
864 IWbemLocator* WbemLocator =
nullptr;
865 IWbemServices* WbemServices =
nullptr;
866 IEnumWbemClassObject* EnumWbem =
nullptr;
869 hr = CoInitializeEx(0, COINIT_MULTITHREADED);
870 hr = CoInitializeSecurity(
nullptr, -1,
nullptr,
nullptr, RPC_C_AUTHN_LEVEL_DEFAULT, RPC_C_IMP_LEVEL_IMPERSONATE,
nullptr, EOAC_NONE,
nullptr);
871 hr = CoCreateInstance(CLSID_WbemLocator, 0, CLSCTX_INPROC_SERVER, IID_IWbemLocator, (LPVOID*)&WbemLocator);
872 if (WbemLocator !=
nullptr) {
874 hr = WbemLocator->ConnectServer(L
"ROOT\\CIMV2",
nullptr,
nullptr, 0, 0, 0, 0, &WbemServices);
875 if (WbemServices !=
nullptr) {
877 hr = WbemServices->ExecQuery(L
"WQL", L
"SELECT ProcessId, CommandLine FROM Win32_Process", WBEM_FLAG_FORWARD_ONLY,
nullptr, &EnumWbem);
879 if (EnumWbem !=
nullptr) {
880 IWbemClassObject* result =
nullptr;
881 ULONG returnedCount = 0;
883 while ((hr = EnumWbem->Next(WBEM_INFINITE, 1, &result, &returnedCount)) == S_OK) {
888 hr = result->Get(L
"ProcessId", 0, &ProcessId, 0, 0);
889 hr = result->Get(L
"CommandLine", 0, &CommandLine, 0, 0);
890 if (!(CommandLine.vt == VT_NULL) && ProcessId.uintVal == (
unsigned int)pid) {
892 int res = WideCharToMultiByte(CP_UTF8, 0, CommandLine.bstrVal, -1,
nullptr, 0,
nullptr,
nullptr);
893 info.arguments.resize(res);
894 WideCharToMultiByte(CP_UTF8, 0, CommandLine.bstrVal, -1, &
info.arguments[0], res,
nullptr,
nullptr);
895 size_t idx =
info.arguments.find(
' ');
896 if (idx ==
info.arguments.npos) {
897 info.arguments.clear();
899 info.arguments =
info.arguments.substr(idx + 2);
902 VariantClear(&ProcessId);
903 VariantClear(&CommandLine);
912 WbemServices->Release();
915 WbemLocator->Release();
919#elif defined(__APPLE__)
921 size_t length =
sizeof(procInfo);
923 int mib[4] = {CTL_KERN, KERN_PROC, KERN_PROC_PID, pid};
925 if (!sysctl(mib, 4, &procInfo, &length,
nullptr, 0)) {
926 info.name = procInfo.kp_proc.p_comm;
927 info.pid = procInfo.kp_proc.p_pid;
930 mib[1] = KERN_PROCARGS;
935 int result = sysctl(mib, 3,
nullptr, &argv_len,
nullptr, 0);
937 yCError(SYSTEMINFO,
"sysctl: %d, %s", errno, strerror(errno));
942 proc_argv = (
char*)malloc(
sizeof(
char) * argv_len);
943 result = sysctl(mib, 3, proc_argv, &argv_len,
nullptr, 0);
945 yCError(SYSTEMINFO,
"sysctl: %d, %s", errno, strerror(errno));
953 while (index < argv_len && proc_argv[index] !=
'\0') {
962 std::stringstream arguments;
963 while (index < argv_len) {
964 if (proc_argv[index] ==
'\0' && index != argv_len - 1) {
967 arguments << proc_argv[index];
973 info.arguments = arguments.str();
An abstraction for a periodic thread.
virtual void run()=0
Loop function.
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 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.