iostat_darwin.c 3.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129
  1. // https://github.com/lufia/iostat/blob/9f7362b77ad333b26c01c99de52a11bdb650ded2/iostat_darwin.c
  2. #include <stdint.h>
  3. #include <CoreFoundation/CoreFoundation.h>
  4. #include "iostat_darwin.h"
  5. #define IOKIT 1 /* to get io_name_t in device_types.h */
  6. #include <IOKit/IOKitLib.h>
  7. #include <IOKit/storage/IOBlockStorageDriver.h>
  8. #include <IOKit/storage/IOMedia.h>
  9. #include <IOKit/IOBSD.h>
  10. #include <mach/mach_host.h>
  11. static int getdrivestat(io_registry_entry_t d, DriveStats *stat);
  12. static int fillstat(io_registry_entry_t d, DriveStats *stat);
  13. int
  14. gopsutil_v3_readdrivestat(DriveStats a[], int n)
  15. {
  16. CFMutableDictionaryRef match;
  17. io_iterator_t drives;
  18. io_registry_entry_t d;
  19. kern_return_t status;
  20. int na, rv;
  21. match = IOServiceMatching("IOMedia");
  22. CFDictionaryAddValue(match, CFSTR(kIOMediaWholeKey), kCFBooleanTrue);
  23. status = IOServiceGetMatchingServices(0, match, &drives);
  24. if(status != KERN_SUCCESS)
  25. return -1;
  26. na = 0;
  27. while(na < n && (d=IOIteratorNext(drives)) > 0){
  28. rv = getdrivestat(d, &a[na]);
  29. if(rv < 0)
  30. return -1;
  31. if(rv > 0)
  32. na++;
  33. IOObjectRelease(d);
  34. }
  35. IOObjectRelease(drives);
  36. return na;
  37. }
  38. static int
  39. getdrivestat(io_registry_entry_t d, DriveStats *stat)
  40. {
  41. io_registry_entry_t parent;
  42. kern_return_t status;
  43. CFDictionaryRef props;
  44. CFStringRef name;
  45. CFNumberRef num;
  46. int rv;
  47. memset(stat, 0, sizeof *stat);
  48. status = IORegistryEntryGetParentEntry(d, kIOServicePlane, &parent);
  49. if(status != KERN_SUCCESS)
  50. return -1;
  51. if(!IOObjectConformsTo(parent, "IOBlockStorageDriver")){
  52. IOObjectRelease(parent);
  53. return 0;
  54. }
  55. status = IORegistryEntryCreateCFProperties(d, (CFMutableDictionaryRef *)&props, kCFAllocatorDefault, kNilOptions);
  56. if(status != KERN_SUCCESS){
  57. IOObjectRelease(parent);
  58. return -1;
  59. }
  60. name = (CFStringRef)CFDictionaryGetValue(props, CFSTR(kIOBSDNameKey));
  61. CFStringGetCString(name, stat->name, NAMELEN, CFStringGetSystemEncoding());
  62. num = (CFNumberRef)CFDictionaryGetValue(props, CFSTR(kIOMediaSizeKey));
  63. CFNumberGetValue(num, kCFNumberSInt64Type, &stat->size);
  64. num = (CFNumberRef)CFDictionaryGetValue(props, CFSTR(kIOMediaPreferredBlockSizeKey));
  65. CFNumberGetValue(num, kCFNumberSInt64Type, &stat->blocksize);
  66. CFRelease(props);
  67. rv = fillstat(parent, stat);
  68. IOObjectRelease(parent);
  69. if(rv < 0)
  70. return -1;
  71. return 1;
  72. }
  73. static struct {
  74. char *key;
  75. size_t off;
  76. } statstab[] = {
  77. {kIOBlockStorageDriverStatisticsBytesReadKey, offsetof(DriveStats, read)},
  78. {kIOBlockStorageDriverStatisticsBytesWrittenKey, offsetof(DriveStats, written)},
  79. {kIOBlockStorageDriverStatisticsReadsKey, offsetof(DriveStats, nread)},
  80. {kIOBlockStorageDriverStatisticsWritesKey, offsetof(DriveStats, nwrite)},
  81. {kIOBlockStorageDriverStatisticsTotalReadTimeKey, offsetof(DriveStats, readtime)},
  82. {kIOBlockStorageDriverStatisticsTotalWriteTimeKey, offsetof(DriveStats, writetime)},
  83. {kIOBlockStorageDriverStatisticsLatentReadTimeKey, offsetof(DriveStats, readlat)},
  84. {kIOBlockStorageDriverStatisticsLatentWriteTimeKey, offsetof(DriveStats, writelat)},
  85. };
  86. static int
  87. fillstat(io_registry_entry_t d, DriveStats *stat)
  88. {
  89. CFDictionaryRef props, v;
  90. CFNumberRef num;
  91. kern_return_t status;
  92. typeof(statstab[0]) *bp, *ep;
  93. status = IORegistryEntryCreateCFProperties(d, (CFMutableDictionaryRef *)&props, kCFAllocatorDefault, kNilOptions);
  94. if(status != KERN_SUCCESS)
  95. return -1;
  96. v = (CFDictionaryRef)CFDictionaryGetValue(props, CFSTR(kIOBlockStorageDriverStatisticsKey));
  97. if(v == NULL){
  98. CFRelease(props);
  99. return -1;
  100. }
  101. ep = &statstab[sizeof(statstab)/sizeof(statstab[0])];
  102. for(bp = &statstab[0]; bp < ep; bp++){
  103. CFStringRef s;
  104. s = CFStringCreateWithCString(kCFAllocatorDefault, bp->key, CFStringGetSystemEncoding());
  105. num = (CFNumberRef)CFDictionaryGetValue(v, s);
  106. if(num)
  107. CFNumberGetValue(num, kCFNumberSInt64Type, ((char*)stat)+bp->off);
  108. CFRelease(s);
  109. }
  110. CFRelease(props);
  111. return 0;
  112. }