YARP
Yet Another Robot Platform
SystemInfo.cpp
Go to the documentation of this file.
1/*
2 * SPDX-FileCopyrightText: 2006-2021 Istituto Italiano di Tecnologia (IIT)
3 * SPDX-FileCopyrightText: 2006-2010 RobotCub Consortium
4 * SPDX-License-Identifier: BSD-3-Clause
5 */
6
8
9#include <yarp/os/Os.h>
11
12#include <cstdio>
13#include <cstdlib>
14#include <cstring>
15
16using namespace yarp::os;
17
18#if defined(__linux__)
19# include <arpa/inet.h>
20# include <ifaddrs.h>
21# include <linux/if.h>
22# include <netinet/in.h>
23# include <pwd.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>
29# include <unistd.h>
30
31extern char** environ;
32
33#elif defined(__APPLE__)
34# include <mach/mach.h>
35# include <pwd.h>
36# include <sstream>
37# include <sys/mount.h>
38# include <sys/param.h>
39# include <sys/sysctl.h>
40# include <sys/types.h>
41# include <unistd.h>
42
43namespace {
44
45YARP_OS_LOG_COMPONENT(SYSTEMINFO, "yarp.os.SystemInfo")
46
47} // namespace
48
49#endif
50
51#if defined(_WIN32)
52# include <Lmcons.h>
53# include <comdef.h> // for using bstr_t class
54# include <psapi.h>
55# include <shlobj.h>
56# include <windows.h>
57//#define _WIN32_DCOM
58# include <wbemidl.h>
59# if (defined(WINVER)) && (WINVER >= 0x0502)
60# include <pdh.h>
61# include <pdhmsg.h>
62# pragma comment(lib, "pdh.lib")
63# pragma comment(lib, "psapi.lib") // for get proocess name for pid
64# pragma comment(lib, "wbemuuid.lib") // for get process arguments from pid
65# endif
66
68# include <yarp/os/Semaphore.h>
69
70# include <vector>
71
72
73static void enableCpuLoadCollector();
74static void disableCpuLoadCollector();
75
76#endif
77
78#if defined(__linux__)
79SystemInfo::capacity_t getMemEntry(const char* tag, const char* bufptr)
80{
81 char* tail;
83 size_t len = strlen(tag);
84 while (bufptr != nullptr) {
85 if (*bufptr == '\n') {
86 bufptr++;
87 }
88 if (strncmp(tag, bufptr, len) == 0) {
89 retval = strtol(bufptr + len, &tail, 10);
90 if (tail == bufptr + len) {
91 return -1;
92 }
93 return retval;
94 }
95 bufptr = strchr(bufptr, '\n');
96 }
97 return -1;
98}
99
100
101bool getCpuEntry(const char* tag, const char* buff, std::string& value)
102{
103 if (strlen(buff) <= strlen(tag)) {
104 return false;
105 }
106
107 if (strncmp(buff, tag, strlen(tag)) != 0) {
108 return false;
109 }
110
111 const char* pos1 = strchr(buff, ':');
112 if (pos1 == nullptr) {
113 return false;
114 }
115
116 while ((*pos1 != '\0') && ((*pos1 == ' ') || (*pos1 == ':') || (*pos1 == '\t'))) {
117 pos1++;
118 }
119 const char* pos2 = buff + strlen(buff) - 1;
120 while ((*pos2 != ':') && ((*pos2 == ' ') || (*pos2 == '\n'))) {
121 pos2--;
122 }
123 if (pos2 < pos1) {
124 return false;
125 }
126 value = std::string(pos1, pos2 - pos1 + 1);
127 return true;
128}
129#endif
130
131
132#if defined(_WIN32)
133class CpuLoadCollector : public yarp::os::PeriodicThread
134{
135public:
136 CpuLoadCollector() :
138 {
139 firstRun = true;
140 load.cpuLoad1 = 0.0;
141 load.cpuLoad5 = 0.0;
142 load.cpuLoad15 = 0.0;
143 load.cpuLoadInstant = (int)0;
144 }
145
146 ~CpuLoadCollector()
147 {
148 }
149
150 void run()
151 {
152 sem.wait();
153 load.cpuLoadInstant = (int)phdCpuLoad();
154 samples.push_back(load.cpuLoadInstant);
155 if (samples.size() > 180)
156 samples.erase(samples.begin());
157
158 std::vector<int>::reverse_iterator rti;
159 int sum = 0;
160 int n = 0;
161 for (rti = samples.rbegin(); rti < samples.rend(); ++rti) {
162 sum += (*rti);
163 n++;
164 // every 1min
165 if (n < 12)
166 load.cpuLoad1 = (double)(sum / n) / 100.0;
167 // every 5min
168 if (n < 60)
169 load.cpuLoad5 = (double)(sum / n) / 100.0;
170 // every 15min
171 load.cpuLoad15 = (double)(sum / n) / 100.0;
172 }
173 sem.post();
174 }
175
176 SystemInfo::LoadInfo getCpuLoad()
177 {
178 sem.wait();
179 SystemInfo::LoadInfo ld = load;
180 sem.post();
181 return ld;
182 }
183
184 //bool threadInit()
185 //void threadRelease()
186private:
187# if (defined(WINVER)) && (WINVER >= 0x0502)
188 double phdCpuLoad()
189 {
190 DWORD ret;
191 if (firstRun) {
192 phdStatus = PdhOpenQuery(nullptr, 0, &hPhdQuery);
193 if (phdStatus != ERROR_SUCCESS)
194 return 0;
195
196 PdhAddCounter(hPhdQuery, TEXT("\\Processor(_Total)\\% Processor Time"), 0, &phdCounter);
197 PdhCollectQueryData(hPhdQuery);
198 firstRun = false;
199 return 0;
200 }
201
202 phdStatus = PdhCollectQueryData(hPhdQuery);
203 if (phdStatus != ERROR_SUCCESS)
204 return 0;
205 phdStatus = PdhGetFormattedCounterValue(phdCounter,
206 PDH_FMT_DOUBLE | PDH_FMT_NOCAP100,
207 &ret,
208 &phdFmtValue);
209 if (phdStatus != ERROR_SUCCESS)
210 return 0;
211 return phdFmtValue.doubleValue;
212 }
213# else
214 double phdCpuLoad()
215 {
216 return 0.0;
217 }
218# endif
219
220private:
221# if (defined(WINVER)) && (WINVER >= 0x0502)
222 PDH_STATUS phdStatus;
223 HQUERY hPhdQuery;
224 PDH_FMT_COUNTERVALUE phdFmtValue;
225 HCOUNTER phdCounter;
226# endif
227 bool firstRun;
229 std::vector<int> samples;
231};
232
233static CpuLoadCollector* globalLoadCollector = nullptr;
234
235void enableCpuLoadCollector()
236{
237 if (globalLoadCollector == nullptr) {
238 globalLoadCollector = new CpuLoadCollector();
239 globalLoadCollector->start();
240 }
241}
242
243void disableCpuLoadCollector()
244{
245 if (globalLoadCollector) {
246 globalLoadCollector->stop();
247 delete globalLoadCollector;
248 globalLoadCollector = nullptr;
249 }
250}
251
252#endif
253
254
255SystemInfo::MemoryInfo SystemInfo::getMemoryInfo()
256{
257 MemoryInfo memory;
258 memory.totalSpace = 0;
259 memory.freeSpace = 0;
260
261#if defined(_WIN32)
262 MEMORYSTATUSEX statex;
263 statex.dwLength = sizeof(statex);
264 if (GlobalMemoryStatusEx(&statex)) {
265 memory.totalSpace = (capacity_t)(statex.ullTotalPhys / 1048576); //in Mb
266 memory.freeSpace = (capacity_t)(statex.ullAvailPhys / 1048576); //in Mb
267 }
268#endif
269
270#if defined(__linux__)
271 char buffer[128];
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) {
277 memory.totalSpace = ret / 1024;
278 }
279
280 if ((ret = getMemEntry("MemFree:", buffer)) > 0) {
281 memory.freeSpace = ret / 1024;
282 }
283 }
284 fclose(procmem);
285 }
286#elif defined(__APPLE__)
287
288 vm_size_t page_size;
289 mach_port_t mach_port;
290 mach_msg_type_number_t count;
291 vm_statistics64_data_t vm_stats;
292
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)) {
296 //These seem to return the # of pages
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;
300
301 int64_t total = totalPages * page_size;
302 int64_t freeSpace = inactivePages * page_size;
303
304 memory.totalSpace = total / 1024;
305 memory.freeSpace = freeSpace / 1024;
306 }
307
308#endif
309
310
311 return memory;
312}
313
314
316{
317 StorageInfo storage;
318 storage.totalSpace = 0;
319 storage.freeSpace = 0;
320
321#if defined(_WIN32)
322
323 DWORD dwSectorsPerCluster = 0, dwBytesPerSector = 0;
324 DWORD dwFreeClusters = 0, dwTotalClusters = 0;
325 std::string strHome = getUserInfo().homeDir;
326 if (strHome.empty())
327 strHome = "C:\\";
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);
331 }
332#endif
333
334#if defined(__linux__)
335 std::string strHome = getUserInfo().homeDir;
336 if (strHome.empty()) {
337 strHome = "/home";
338 }
339
340 struct statvfs vfs;
341 if (statvfs(strHome.c_str(), &vfs) == 0) {
342 storage.totalSpace = (int)(vfs.f_blocks * vfs.f_bsize / (1048576)); // in MB
343 storage.freeSpace = (int)(vfs.f_bavail * vfs.f_bsize / (1048576)); // in MB
344 }
345
346#endif
347
348#if defined(__APPLE__)
349 std::string strHome = getUserInfo().homeDir;
350 if (strHome.empty())
351 strHome = "/";
352
353 struct statfs vfs;
354 if (statfs(strHome.c_str(), &vfs) == 0) {
355 storage.totalSpace = (int)(vfs.f_blocks * vfs.f_bsize / (1048576)); // in MB
356 storage.freeSpace = (int)(vfs.f_bavail * vfs.f_bsize / (1048576)); // in MB
357 }
358#endif
359
360 return storage;
361}
362
363/*
364SystemInfo::NetworkInfo SystemInfo::getNetworkInfo()
365{
366 NetworkInfo network;
367
368#if defined(__linux__)
369
370 struct ifaddrs * ifAddrStruct=nullptr;
371 struct ifaddrs * ifa=nullptr;
372 void * tmpAddrPtr=nullptr;
373
374 getifaddrs(&ifAddrStruct);
375 for (ifa = ifAddrStruct; ifa != nullptr; ifa = ifa->ifa_next)
376 {
377 if (ifa ->ifa_addr->sa_family == AF_INET)
378 {
379 // is a valid IP4 Address
380 tmpAddrPtr = &((struct sockaddr_in *)ifa->ifa_addr)->sin_addr;
381 char addressBuffer[INET_ADDRSTRLEN];
382 const char* ret = inet_ntop(AF_INET, tmpAddrPtr, addressBuffer, INET_ADDRSTRLEN);
383 if (ret && (strcmp(ifa->ifa_name, "eth0") == 0))
384 network.ip4 = addressBuffer;
385 }
386 else if (ifa->ifa_addr->sa_family == AF_INET6)
387 {
388 // is a valid IP6 Address
389 tmpAddrPtr=&((struct sockaddr_in6 *)ifa->ifa_addr)->sin6_addr;
390 char addressBuffer[INET6_ADDRSTRLEN];
391 const char* ret = inet_ntop(AF_INET6, tmpAddrPtr, addressBuffer, INET6_ADDRSTRLEN);
392 if (ret && (strcmp(ifa->ifa_name, "eth0") == 0))
393 network.ip6 = addressBuffer;
394 }
395 }
396
397 if (ifAddrStruct)
398 freeifaddrs(ifAddrStruct);
399
400 // getting mac addrress
401 struct ifreq ifr;
402 struct ifreq *IFR;
403 struct ifconf ifc;
404 char buf[1024];
405 int s;
406 bool found = false;
407
408 if ( (s = socket(AF_INET, SOCK_DGRAM, 0)) == -1 )
409 return network;
410
411 ifc.ifc_len = sizeof(buf);
412 ifc.ifc_buf = buf;
413 ioctl(s, SIOCGIFCONF, &ifc);
414 IFR = ifc.ifc_req;
415 for (int i = ifc.ifc_len/sizeof(struct ifreq); --i >= 0; IFR++)
416 {
417 strcpy(ifr.ifr_name, IFR->ifr_name);
418 if (ioctl(s, SIOCGIFFLAGS, &ifr) == 0)
419 {
420 if (!(ifr.ifr_flags & IFF_LOOPBACK))
421 {
422 if (ioctl(s, SIOCGIFHWADDR, &ifr) == 0)
423 {
424 found = true;
425 break;
426 }
427 }
428 }
429 }
430 close(s);
431
432 if (found)
433 {
434 unsigned char addr[6];
435 char mac[32];
436 bcopy(ifr.ifr_hwaddr.sa_data, addr, 6);
437 sprintf(mac, "%2.2x:%2.2x:%2.2x:%2.2x:%2.2x:%2.2x",
438 addr[0], addr[1], addr[2], addr[3], addr[4], addr[5]);
439 network.mac = mac;
440 }
441
442#endif
443 return network;
444}
445*/
446
447
449{
450 ProcessorInfo processor;
451 processor.cores = 0;
452 processor.frequency = 0.0;
453 processor.family = 0;
454 processor.modelNumber = 0;
455 processor.siblings = 0;
456
457#if defined(_WIN32)
458 SYSTEM_INFO sysinf;
459 GetSystemInfo(&sysinf);
460 switch (sysinf.wProcessorArchitecture) {
461 case PROCESSOR_ARCHITECTURE_AMD64: {
462 processor.architecture = "X64";
463 break;
464 }
465 case PROCESSOR_ARCHITECTURE_IA64: {
466 processor.architecture = "Intel Itanium-based";
467 break;
468 }
469 case PROCESSOR_ARCHITECTURE_INTEL: {
470 processor.architecture = "X86";
471 break;
472 }
473 default:
474 processor.architecture = "Unknown";
475 };
476 processor.siblings = sysinf.dwNumberOfProcessors;
477 processor.modelNumber = sysinf.dwProcessorType;
478 switch (sysinf.dwProcessorType) {
479 case PROCESSOR_INTEL_386: {
480 processor.model = "PROCESSOR_INTEL_386";
481 break;
482 }
483 case PROCESSOR_INTEL_486: {
484 processor.model = "PROCESSOR_INTEL_486";
485 break;
486 }
487 case PROCESSOR_INTEL_PENTIUM: {
488 processor.model = "PROCESSOR_INTEL_PENTIUM";
489 break;
490 }
491 case PROCESSOR_INTEL_IA64: {
492 processor.model = "PROCESSOR_INTEL_IA64";
493 break;
494 }
495 case PROCESSOR_AMD_X8664: {
496 processor.model = "PROCESSOR_AMD_X8664";
497 break;
498 }
499 };
500
501 DWORD dwMHz;
502 DWORD BufSize = sizeof(DWORD);
503 HKEY hKey;
504 if (RegOpenKeyEx(HKEY_LOCAL_MACHINE,
505 "HARDWARE\\DESCRIPTION\\System\\CentralProcessor\\0",
506 0,
507 KEY_READ,
508 &hKey)
509 == ERROR_SUCCESS) {
510 RegQueryValueEx(hKey, "~MHz", nullptr, nullptr, (LPBYTE)&dwMHz, &BufSize);
511 processor.frequency = (double)dwMHz;
512 RegCloseKey(hKey);
513 }
514
515 // TODO: this should be fixed to obtain correct number of physical cores
516 processor.cores = 1;
517
518#endif
519
520#if defined(__linux__)
521 char buffer[128];
522 FILE* proccpu = fopen("/proc/cpuinfo", "r");
523 if (proccpu != nullptr) {
524 while (fgets(buffer, 128, proccpu) != nullptr) {
525 std::string value;
526 if (getCpuEntry("model", buffer, value) && !getCpuEntry("model name", buffer, value)) {
527 processor.modelNumber = atoi(value.c_str());
528 }
529 if (getCpuEntry("model name", buffer, value)) {
530 processor.model = value;
531 }
532 if (getCpuEntry("vendor_id", buffer, value)) {
533 processor.vendor = value;
534 }
535 if (getCpuEntry("cpu family", buffer, value)) {
536 processor.family = atoi(value.c_str());
537 }
538 if (getCpuEntry("cpu cores", buffer, value)) {
539 processor.cores = atoi(value.c_str());
540 }
541 if (getCpuEntry("siblings", buffer, value)) {
542 processor.siblings = atoi(value.c_str());
543 }
544 if (getCpuEntry("cpu MHz", buffer, value)) {
545 processor.frequency = atof(value.c_str());
546 }
547 }
548 fclose(proccpu);
549 }
550
551 struct utsname uts;
552 if (uname(&uts) == 0) {
553 processor.architecture = uts.machine;
554 }
555#elif defined(__APPLE__)
556 // std::string architecture;
557
558 int mib[] = {CTL_HW, HW_CPU_FREQ};
559 int64_t value = 0;
560 size_t length = sizeof(value);
561
562 if (!sysctl(mib, 2, &value, &length, nullptr, 0)) {
563 processor.frequency = value / 1e+6; //this is in Hz. What is the expected frequency?
564 }
565
566 if (!sysctlbyname("hw.logicalcpu", &value, &length, nullptr, 0)) {
567 processor.cores = value; //this is the number of cores
568 //or cpus: hw.physicalcpu
569 }
570
571 char buff[513];
572 size_t buffLen = 512;
573 if (!sysctlbyname("machdep.cpu.vendor", buff, &buffLen, nullptr, 0)) {
574 processor.vendor = buff; //this is the number of cores
575 //or cpus: hw.physicalcpu
576 }
577 buffLen = 512;
578 if (!sysctlbyname("machdep.cpu.brand_string", buff, &buffLen, nullptr, 0)) {
579 processor.model = buff; //this is the number of cores
580 //or cpus: hw.physicalcpu
581 }
582 if (!sysctlbyname("machdep.cpu.family", &value, &length, nullptr, 0)) {
583 processor.family = value; //this is the number of cores
584 //or cpus: hw.physicalcpu
585 }
586 if (!sysctlbyname("machdep.cpu.model", &value, &length, nullptr, 0)) {
587 processor.modelNumber = value; //this is the number of cores
588 //or cpus: hw.physicalcpu
589 }
590
591
592#endif
593 return processor;
594}
595
596
598{
599 PlatformInfo platform;
600
601#if defined(_WIN32)
602 platform.name = "Windows";
603 OSVERSIONINFOEX osver;
604 osver.dwOSVersionInfoSize = sizeof(osver);
605 if (GetVersionEx((LPOSVERSIONINFO)&osver)) {
606 char buff[64];
607 sprintf(buff, "%d.%d", osver.dwMajorVersion, osver.dwMinorVersion);
608 platform.release = buff;
609 platform.codename = buff;
610 if ((osver.dwMajorVersion == 10) && (osver.dwMinorVersion == 0) && (osver.wProductType == VER_NT_WORKSTATION)) {
611 platform.distribution = "10";
612 } else if ((osver.dwMajorVersion == 10) && (osver.dwMinorVersion == 0) && (osver.wProductType != VER_NT_WORKSTATION)) {
613 platform.distribution = "Server 2016";
614 } else if ((osver.dwMajorVersion == 6) && (osver.dwMinorVersion == 2) && (osver.wProductType == VER_NT_WORKSTATION)) {
615 platform.distribution = "8.1";
616 } else if ((osver.dwMajorVersion == 6) && (osver.dwMinorVersion == 3) && (osver.wProductType != VER_NT_WORKSTATION)) {
617 platform.distribution = "Server 2012 R2";
618 } else if ((osver.dwMajorVersion == 6) && (osver.dwMinorVersion == 2) && (osver.wProductType == VER_NT_WORKSTATION)) {
619 platform.distribution = "8";
620 } else if ((osver.dwMajorVersion == 6) && (osver.dwMinorVersion == 2) && (osver.wProductType != VER_NT_WORKSTATION)) {
621 platform.distribution = "Server 2012";
622 } else if ((osver.dwMajorVersion == 6) && (osver.dwMinorVersion == 1) && (osver.wProductType == VER_NT_WORKSTATION)) {
623 platform.distribution = "7";
624 } else if ((osver.dwMajorVersion == 6) && (osver.dwMinorVersion == 1) && (osver.wProductType != VER_NT_WORKSTATION)) {
625 platform.distribution = "Server 2008 R2";
626 } else if ((osver.dwMajorVersion == 6) && (osver.dwMinorVersion == 0) && (osver.wProductType == VER_NT_WORKSTATION)) {
627 platform.distribution = "Vista";
628 } else if ((osver.dwMajorVersion == 6) && (osver.dwMinorVersion == 0) && (osver.wProductType != VER_NT_WORKSTATION)) {
629 platform.distribution = "Server 2008";
630 } else if ((osver.dwMajorVersion == 5) && (osver.dwMinorVersion == 2)) {
631 platform.distribution = "Server 2003";
632 // } else if ((osver.dwMajorVersion == 5) && (osver.dwMinorVersion == 2) && (osver.wSuiteMask & VER_SUITE_WH_SERVER)) {
633 // platform.distribution = "Home Server";
634 // } else if ((osver.dwMajorVersion == 5) && (osver.dwMinorVersion == 2) && (GetSystemMetrics(SM_SERVERR2) != 0)) {
635 // platform.distribution = "Server 2003 R2";
636 } else if ((osver.dwMajorVersion == 5) && (osver.dwMinorVersion == 2) && (osver.wProductType == VER_NT_WORKSTATION)) /* &&(osver.wProcessorArchitecture == PROCESSOR_ARCHITECTURE_AMD64)*/ {
637 platform.distribution = "XP Professional x64 Edition";
638 } else if ((osver.dwMajorVersion == 5) && (osver.dwMinorVersion == 1)) {
639 platform.distribution = "XP";
640 } else if ((osver.dwMajorVersion == 5) && (osver.dwMinorVersion == 0)) {
641 platform.distribution = "2000";
642 }
643 }
644
645 const char* a = GetEnvironmentStrings();
646 size_t prev = 0;
647 for (size_t i = 0;; i++) {
648 if (a[i] == '\0') {
649 std::string tmpVariable(a + prev, a + i);
650 size_t equalsSign = tmpVariable.find("=");
651 if (equalsSign != std::string::npos && equalsSign != 0) // among environment variables there are DOS-related ones that start with a =
652 {
653 platform.environmentVars.put(tmpVariable.substr(0, equalsSign), tmpVariable.substr(equalsSign + 1));
654 }
655 prev = i + 1;
656 if (a[i + 1] == '\0') {
657 break;
658 }
659 }
660 }
661
662#endif
663
664#if defined(__linux__)
665 struct utsname uts;
666 if (uname(&uts) == 0) {
667 platform.name = uts.sysname;
668 platform.kernel = uts.release;
669 } else {
670 platform.name = "Linux";
671 }
672
673 char buffer[128];
674 FILE* release = popen("lsb_release -ric", "r");
675 if (release != nullptr) {
676 while (fgets(buffer, 128, release) != nullptr) {
677 std::string value;
678 if (getCpuEntry("Distributor ID", buffer, value)) {
679 platform.distribution = value;
680 }
681 if (getCpuEntry("Release", buffer, value)) {
682 platform.release = value;
683 }
684 if (getCpuEntry("Codename", buffer, value)) {
685 platform.codename = value;
686 }
687 }
688 pclose(release);
689 }
690
691 char* varChar = *environ;
692
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));
698 }
699 varChar = *(environ + i);
700 }
701#endif
702
703#if defined(__APPLE__)
704
705 char buff[513];
706 size_t buffLen = 512;
707 if (!sysctlbyname("kern.ostype", buff, &buffLen, nullptr, 0)) {
708 platform.name = buff;
709 }
710
711 if (!sysctlbyname("kern.osrelease", buff, &buffLen, nullptr, 0)) {
712 platform.release = buff;
713 }
714
715#endif
716 return platform;
717}
718
719
721{
722 UserInfo user;
723 user.userID = 0;
724
725#if defined(_WIN32)
726 char path[MAX_PATH + 1];
727 if (SHGetFolderPathA(nullptr, CSIDL_PROFILE, nullptr, 0, path) == S_OK)
728 user.homeDir = path;
729
730 char username[UNLEN + 1];
731 DWORD nsize = UNLEN + 1;
732 if (GetUserName(username, &nsize)) {
733 user.userName = username;
734 user.realName = username;
735 }
736#endif
737
738#if defined(__linux__) || defined(__APPLE__)
739 struct passwd* pwd = getpwuid(getuid());
740 user.userID = getuid();
741 if (pwd != nullptr) {
742 user.userName = pwd->pw_name;
743 user.realName = pwd->pw_gecos;
744 user.homeDir = pwd->pw_dir;
745 }
746#endif
747 return user;
748}
749
750
752{
753 LoadInfo load;
754 load.cpuLoad1 = 0.0;
755 load.cpuLoad5 = 0.0;
756 load.cpuLoad15 = 0.0;
757 load.cpuLoadInstant = 0;
758
759#if defined(_WIN32)
760 if (globalLoadCollector) {
761 load = globalLoadCollector->getCpuLoad();
762 int siblings = getProcessorInfo().siblings;
763 if (siblings > 1) {
764 load.cpuLoad1 *= siblings;
765 load.cpuLoad5 *= siblings;
766 load.cpuLoad15 *= siblings;
767 }
768 }
769#endif
770
771#if defined(__linux__)
772 FILE* procload = fopen("/proc/loadavg", "r");
773 if (procload != nullptr) {
774 char buff[128];
775 int ret = fscanf(procload, "%lf %lf %lf %s", &(load.cpuLoad1), &(load.cpuLoad5), &(load.cpuLoad15), buff);
776 if (ret > 0) {
777 char* tail = strchr(buff, '/');
778 if ((tail != nullptr) && (tail != buff)) {
779 load.cpuLoadInstant = (int)(strtol(buff, &tail, 0) - 1);
780 }
781 }
782 fclose(procload);
783 }
784#endif
785
786#if defined(__APPLE__)
787
788 mach_msg_type_number_t count = HOST_CPU_LOAD_INFO_COUNT;
789 host_cpu_load_info_data_t cpu_load;
790
791 if (KERN_SUCCESS == host_statistics(mach_host_self(), HOST_CPU_LOAD_INFO, (host_info64_t)&cpu_load, &count)) {
792 //How to map this information into yarp structure?
793 natural_t total = 0;
794 for (int i = 0; i < CPU_STATE_MAX; ++i) {
795 total += cpu_load.cpu_ticks[i];
796 }
797
798 load.cpuLoad1 = 100.0 * cpu_load.cpu_ticks[CPU_STATE_USER] / total;
799 }
800#endif
801 return load;
802}
803
804
806{
807 // If not specified, get information for current process
808 if (pid == 0) {
809 pid = yarp::os::getpid();
810 }
811
813 info.pid = -1; // invalid
814 info.schedPolicy = -1;
815 info.schedPriority = -1;
816#if defined(__linux__)
817 FILE* file;
818 char cmdline[256] = {0};
819 char filename[256];
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);
824 fclose(file);
825 if (p != nullptr) {
826 while (*p != 0) {
827 p += strlen(p);
828 if (*(p + 1) != 0) {
829 *p = ' ';
830 }
831 p++;
832 }
833 info.pid = pid;
834 // split the cmdline to find the arguments
835 info.name = cmdline;
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);
841 }
842 }
843 }
844
845 // scheduling params
846 struct sched_param param;
847 if (sched_getparam(pid, &param) == 0) {
848 info.schedPriority = param.__sched_priority;
849 }
850 info.schedPolicy = sched_getscheduler(pid);
851
852#elif defined(_WIN32)
853 HANDLE hnd = OpenProcess(PROCESS_QUERY_INFORMATION | PROCESS_VM_READ, FALSE, pid);
854 if (hnd) {
855 TCHAR filename[MAX_PATH];
856 if (GetModuleBaseName(hnd, 0, filename, MAX_PATH)) {
857 info.name = filename;
858 info.pid = pid;
859 }
860 CloseHandle(hnd);
861 }
862 // reterieving arguments
863 HRESULT hr = 0;
864 IWbemLocator* WbemLocator = nullptr;
865 IWbemServices* WbemServices = nullptr;
866 IEnumWbemClassObject* EnumWbem = nullptr;
867
868 //initializate the Windows security
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) {
873 //connect to the WMI
874 hr = WbemLocator->ConnectServer(L"ROOT\\CIMV2", nullptr, nullptr, 0, 0, 0, 0, &WbemServices);
875 if (WbemServices != nullptr) {
876 //Run the WQL Query
877 hr = WbemServices->ExecQuery(L"WQL", L"SELECT ProcessId, CommandLine FROM Win32_Process", WBEM_FLAG_FORWARD_ONLY, nullptr, &EnumWbem);
878 // Iterate over the enumerator
879 if (EnumWbem != nullptr) {
880 IWbemClassObject* result = nullptr;
881 ULONG returnedCount = 0;
882
883 while ((hr = EnumWbem->Next(WBEM_INFINITE, 1, &result, &returnedCount)) == S_OK) {
884 VARIANT ProcessId;
885 VARIANT CommandLine;
886
887 // access the properties
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) {
891 // covert BSTR to std::string
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();
898 } else {
899 info.arguments = info.arguments.substr(idx + 2); // it seems windows adds two spaces after the program name
900 }
901 info.pid = pid;
902 VariantClear(&ProcessId);
903 VariantClear(&CommandLine);
904 break;
905 }
906 result->Release();
907 } // end while
908
909 EnumWbem->Release();
910 } // end if EnumWbem
911
912 WbemServices->Release();
913 } // end if WbemServices
914
915 WbemLocator->Release();
916 } // end if WbemLocator
917
918 CoUninitialize();
919#elif defined(__APPLE__)
920 kinfo_proc procInfo;
921 size_t length = sizeof(procInfo);
922
923 int mib[4] = {CTL_KERN, KERN_PROC, KERN_PROC_PID, pid};
924
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;
928
929 //Some info here: https://gist.github.com/nonowarn/770696
930 mib[1] = KERN_PROCARGS;
931 mib[2] = pid;
932 char* proc_argv;
933 size_t argv_len;
934 //getting length of execute string
935 int result = sysctl(mib, 3, nullptr, &argv_len, nullptr, 0);
936 if (result != 0) {
937 yCError(SYSTEMINFO, "sysctl: %d, %s", errno, strerror(errno));
938 return info;
939 }
940
941 //now getting the string
942 proc_argv = (char*)malloc(sizeof(char) * argv_len);
943 result = sysctl(mib, 3, proc_argv, &argv_len, nullptr, 0);
944 if (result != 0) {
945 yCError(SYSTEMINFO, "sysctl: %d, %s", errno, strerror(errno));
946 free(proc_argv);
947 return info;
948 }
949
950 //looking for '\0', i.e. NULL char
951 //skip first string which is the executable
952 size_t index = 0;
953 while (index < argv_len && proc_argv[index] != '\0') {
954 index++;
955 }
956 index++;
957 //now we have to split the remaining string
958 //Note: this is not easy. We don't know the format
959 //See: http://lists.apple.com/archives/darwin-kernel/2012/Mar/msg00025.html
960 //for example, I get both arguments and environment variables
961
962 std::stringstream arguments;
963 while (index < argv_len) {
964 if (proc_argv[index] == '\0' && index != argv_len - 1) {
965 arguments << " ";
966 } else {
967 arguments << proc_argv[index];
968 }
969 index++;
970 }
971
972 free(proc_argv);
973 info.arguments = arguments.str();
974 }
975
976#endif
977 return info;
978}
int16_t * samples
bool ret
void * HANDLE
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.
Definition: Property.cpp:1015
A class for thread synchronization and mutual exclusion.
Definition: Semaphore.h:25
static ProcessInfo getProcessInfo(int pid=0)
gets the operating system process information given by its PID.
Definition: SystemInfo.cpp:805
static PlatformInfo getPlatformInfo()
getPlatformInfo
Definition: SystemInfo.cpp:597
static UserInfo getUserInfo()
getUserInfo
Definition: SystemInfo.cpp:720
static LoadInfo getLoadInfo()
getLoadInfo
Definition: SystemInfo.cpp:751
static StorageInfo getStorageInfo()
getStorageInfo
Definition: SystemInfo.cpp:315
static ProcessorInfo getProcessorInfo()
getProcessorInfo
Definition: SystemInfo.cpp:448
#define yCError(component,...)
Definition: LogComponent.h:213
#define YARP_OS_LOG_COMPONENT(name, name_string)
Definition: LogComponent.h:29
An interface to the operating system, including Port based communication.
int getpid()
Portable wrapper for the getppid() function.
Definition: Os.cpp:91
ShouldUseSystemClock
Definition: Time.h:19
The LoadInfo struct holds the current cpu load information.
Definition: SystemInfo.h:68
The MemoryInfo struct holds the system memory information.
Definition: SystemInfo.h:33
The PlatformInfo struct holds the operating system information.
Definition: SystemInfo.h:80
yarp::os::Property environmentVars
Definition: SystemInfo.h:86
The ProcessInfo struct provides the operating system process information.
Definition: SystemInfo.h:112
The ProcessorInfo struct holds the processor information.
Definition: SystemInfo.h:52
The StorageInfo struct holds the system storage information.
Definition: SystemInfo.h:43
The UserInfo struct holds the current user information.
Definition: SystemInfo.h:93