• Hadoop-Yarn-NodeManager如何计算Linux系统上的资源信息


    一、上下文

    中讲节点资源监控服务(NodeResourceMonitorImpl)时只是提了下SysInfoLinux,下面我们展开讲下

    SysInfoLinux是用于计算Linux系统上的资源信息的插件

    二、SysInfoLinux源码

    1. package org.apache.hadoop.util;
    2. import java.io.BufferedReader;
    3. import java.io.FileInputStream;
    4. import java.io.FileNotFoundException;
    5. import java.io.InputStreamReader;
    6. import java.io.IOException;
    7. import java.math.BigInteger;
    8. import java.nio.charset.Charset;
    9. import java.util.HashMap;
    10. import java.util.HashSet;
    11. import java.util.regex.Matcher;
    12. import java.util.regex.Pattern;
    13. import com.google.common.annotations.VisibleForTesting;
    14. import org.apache.hadoop.classification.InterfaceAudience;
    15. import org.apache.hadoop.classification.InterfaceStability;
    16. import org.apache.hadoop.util.Shell.ShellCommandExecutor;
    17. import org.slf4j.Logger;
    18. import org.slf4j.LoggerFactory;
    19. /**
    20. * 用于计算Linux系统上的资源信息的插件
    21. */
    22. @InterfaceAudience.Private
    23. @InterfaceStability.Evolving
    24. public class SysInfoLinux extends SysInfo {
    25. private static final Logger LOG =
    26. LoggerFactory.getLogger(SysInfoLinux.class);
    27. /**
    28. * proc的meminfo虚拟文件具有以下格式的键值
    29. * "key:[ \t]*value[ \t]kB".
    30. */
    31. private static final String PROCFS_MEMFILE = "/proc/meminfo";
    32. private static final Pattern PROCFS_MEMFILE_FORMAT =
    33. Pattern.compile("^([a-zA-Z_()]*):[ \t]*([0-9]*)[ \t]*(kB)?");
    34. //我们需要meminfo中以下键的值
    35. private static final String MEMTOTAL_STRING = "MemTotal";
    36. private static final String SWAPTOTAL_STRING = "SwapTotal";
    37. private static final String MEMFREE_STRING = "MemFree";
    38. private static final String SWAPFREE_STRING = "SwapFree";
    39. private static final String INACTIVE_STRING = "Inactive";
    40. private static final String INACTIVEFILE_STRING = "Inactive(file)";
    41. private static final String HARDWARECORRUPTED_STRING = "HardwareCorrupted";
    42. private static final String HUGEPAGESTOTAL_STRING = "HugePages_Total";
    43. private static final String HUGEPAGESIZE_STRING = "Hugepagesize";
    44. /**
    45. * 解析/proc/cpuinfo的样板
    46. */
    47. private static final String PROCFS_CPUINFO = "/proc/cpuinfo";
    48. private static final Pattern PROCESSOR_FORMAT =
    49. Pattern.compile("^processor[ \t]:[ \t]*([0-9]*)");
    50. private static final Pattern FREQUENCY_FORMAT =
    51. Pattern.compile("^cpu MHz[ \t]*:[ \t]*([0-9.]*)");
    52. private static final Pattern PHYSICAL_ID_FORMAT =
    53. Pattern.compile("^physical id[ \t]*:[ \t]*([0-9]*)");
    54. private static final Pattern CORE_ID_FORMAT =
    55. Pattern.compile("^core id[ \t]*:[ \t]*([0-9]*)");
    56. /**
    57. * 解析/proc/stat的样板
    58. */
    59. private static final String PROCFS_STAT = "/proc/stat";
    60. private static final Pattern CPU_TIME_FORMAT =
    61. Pattern.compile("^cpu[ \t]*([0-9]*)" +
    62. "[ \t]*([0-9]*)[ \t]*([0-9]*)[ \t].*");
    63. private CpuTimeTracker cpuTimeTracker;
    64. /**
    65. * 解析/proc/net/dev的样板
    66. */
    67. private static final String PROCFS_NETFILE = "/proc/net/dev";
    68. private static final Pattern PROCFS_NETFILE_FORMAT =
    69. Pattern .compile("^[ \t]*([a-zA-Z]+[0-9]*):" +
    70. "[ \t]*([0-9]+)[ \t]*([0-9]+)[ \t]*([0-9]+)[ \t]*([0-9]+)" +
    71. "[ \t]*([0-9]+)[ \t]*([0-9]+)[ \t]*([0-9]+)[ \t]*([0-9]+)" +
    72. "[ \t]*([0-9]+)[ \t]*([0-9]+)[ \t]*([0-9]+)[ \t]*([0-9]+)" +
    73. "[ \t]*([0-9]+)[ \t]*([0-9]+)[ \t]*([0-9]+)[ \t]*([0-9]+).*");
    74. /**
    75. * 解析/proc/diskstats的样板
    76. */
    77. private static final String PROCFS_DISKSFILE = "/proc/diskstats";
    78. private static final Pattern PROCFS_DISKSFILE_FORMAT =
    79. Pattern.compile("^[ \t]*([0-9]+)[ \t]*([0-9 ]+)" +
    80. "(?!([a-zA-Z]+[0-9]+))([a-zA-Z]+)" +
    81. "[ \t]*([0-9]+)[ \t]*([0-9]+)[ \t]*([0-9]+)[ \t]*([0-9]+)" +
    82. "[ \t]*([0-9]+)[ \t]*([0-9]+)[ \t]*([0-9]+)[ \t]*([0-9]+)" +
    83. "[ \t]*([0-9]+)[ \t]*([0-9]+)[ \t]*([0-9]+)");
    84. /**
    85. * 解析/sys/block/partition_name/queue/hw_sector_size的样板
    86. */
    87. private static final Pattern PROCFS_DISKSECTORFILE_FORMAT =
    88. Pattern.compile("^([0-9]+)");
    89. private String procfsMemFile;
    90. private String procfsCpuFile;
    91. private String procfsStatFile;
    92. private String procfsNetFile;
    93. private String procfsDisksFile;
    94. private long jiffyLengthInMillis;
    95. private long ramSize = 0;
    96. private long swapSize = 0;
    97. private long ramSizeFree = 0; // 机器上的可用 ram 磁盘空间 (kB)
    98. private long swapSizeFree = 0; // 机器上的可用 swap 空间 (kB)
    99. private long inactiveSize = 0; // 不活跃内存 (kB)
    100. private long inactiveFileSize = -1; // 非活动缓存,-1(如果不存在)
    101. private long hardwareCorruptSize = 0; // RAM已损坏且不可用大小
    102. private long hugePagesTotal = 0; // # 保留的标准大页
    103. private long hugePageSize = 0; // # 每个标准大页的大小
    104. /* 系统上的逻辑处理器数量. */
    105. private int numProcessors = 0;
    106. /* 系统上的物理核心数. */
    107. private int numCores = 0;
    108. private long cpuFrequency = 0L; // 系统上的CPU频率 (kHz)
    109. private long numNetBytesRead = 0L; // 从网络读取的聚合字节
    110. private long numNetBytesWritten = 0L; // 写入网络的聚合字节数
    111. private long numDisksBytesRead = 0L; // 从磁盘读取的聚合字节数
    112. private long numDisksBytesWritten = 0L; // 写入磁盘的聚合字节数
    113. private boolean readMemInfoFile = false;
    114. private boolean readCpuInfoFile = false;
    115. /* 为每个磁盘映射其扇区大小 */
    116. private HashMap perDiskSectorSize = null;
    117. public static final long PAGE_SIZE = getConf("PAGESIZE");
    118. public static final long JIFFY_LENGTH_IN_MILLIS =
    119. Math.max(Math.round(1000D / getConf("CLK_TCK")), -1);
    120. private static long getConf(String attr) {
    121. if(Shell.LINUX) {
    122. try {
    123. ShellCommandExecutor shellExecutorClk = new ShellCommandExecutor(
    124. new String[] {"getconf", attr });
    125. shellExecutorClk.execute();
    126. return Long.parseLong(shellExecutorClk.getOutput().replace("\n", ""));
    127. } catch (IOException|NumberFormatException e) {
    128. return -1;
    129. }
    130. }
    131. return -1;
    132. }
    133. /**
    134. * 获取当前时间
    135. * @return Unix时间戳(毫秒)
    136. */
    137. long getCurrentTime() {
    138. return System.currentTimeMillis();
    139. }
    140. public SysInfoLinux() {
    141. this(PROCFS_MEMFILE, PROCFS_CPUINFO, PROCFS_STAT,
    142. PROCFS_NETFILE, PROCFS_DISKSFILE, JIFFY_LENGTH_IN_MILLIS);
    143. }
    144. /**
    145. * 构造函数,它允许分配/proc/目录。这将仅用于单元测试
    146. * @param procfsMemFile fake file for /proc/meminfo
    147. * @param procfsCpuFile fake file for /proc/cpuinfo
    148. * @param procfsStatFile fake file for /proc/stat
    149. * @param procfsNetFile fake file for /proc/net/dev
    150. * @param procfsDisksFile fake file for /proc/diskstats
    151. * @param jiffyLengthInMillis fake jiffy length value
    152. */
    153. @VisibleForTesting
    154. public SysInfoLinux(String procfsMemFile,
    155. String procfsCpuFile,
    156. String procfsStatFile,
    157. String procfsNetFile,
    158. String procfsDisksFile,
    159. long jiffyLengthInMillis) {
    160. this.procfsMemFile = procfsMemFile;
    161. this.procfsCpuFile = procfsCpuFile;
    162. this.procfsStatFile = procfsStatFile;
    163. this.procfsNetFile = procfsNetFile;
    164. this.procfsDisksFile = procfsDisksFile;
    165. this.jiffyLengthInMillis = jiffyLengthInMillis;
    166. this.cpuTimeTracker = new CpuTimeTracker(jiffyLengthInMillis);
    167. this.perDiskSectorSize = new HashMap();
    168. }
    169. /**
    170. * 读 /proc/meminfo, 只解析和计算一次内存信息.
    171. */
    172. private void readProcMemInfoFile() {
    173. readProcMemInfoFile(false);
    174. }
    175. /**
    176. *
    177. * Long.parseLong()的包装器,如果值无效则返回零。在某些情况下,
    178. * /proc/meminfo中的swapFree可能为负数,报告为非常大的十进制值。
    179. */
    180. private long safeParseLong(String strVal) {
    181. long parsedVal;
    182. try {
    183. parsedVal = Long.parseLong(strVal);
    184. } catch (NumberFormatException nfe) {
    185. parsedVal = 0;
    186. }
    187. return parsedVal;
    188. }
    189. /**
    190. * 读 /proc/meminfo, 解析和计算内存信息.
    191. * @param readAgain if false, read only on the first time
    192. */
    193. private void readProcMemInfoFile(boolean readAgain) {
    194. if (readMemInfoFile && !readAgain) {
    195. return;
    196. }
    197. // Read "/proc/memInfo" file
    198. BufferedReader in;
    199. InputStreamReader fReader;
    200. try {
    201. fReader = new InputStreamReader(
    202. new FileInputStream(procfsMemFile), Charset.forName("UTF-8"));
    203. in = new BufferedReader(fReader);
    204. } catch (FileNotFoundException f) {
    205. // shouldn't happen....
    206. LOG.warn("Couldn't read " + procfsMemFile
    207. + "; can't determine memory settings");
    208. return;
    209. }
    210. Matcher mat;
    211. try {
    212. String str = in.readLine();
    213. while (str != null) {
    214. mat = PROCFS_MEMFILE_FORMAT.matcher(str);
    215. if (mat.find()) {
    216. if (mat.group(1).equals(MEMTOTAL_STRING)) {
    217. ramSize = Long.parseLong(mat.group(2));
    218. } else if (mat.group(1).equals(SWAPTOTAL_STRING)) {
    219. swapSize = Long.parseLong(mat.group(2));
    220. } else if (mat.group(1).equals(MEMFREE_STRING)) {
    221. ramSizeFree = safeParseLong(mat.group(2));
    222. } else if (mat.group(1).equals(SWAPFREE_STRING)) {
    223. swapSizeFree = safeParseLong(mat.group(2));
    224. } else if (mat.group(1).equals(INACTIVE_STRING)) {
    225. inactiveSize = Long.parseLong(mat.group(2));
    226. } else if (mat.group(1).equals(INACTIVEFILE_STRING)) {
    227. inactiveFileSize = Long.parseLong(mat.group(2));
    228. } else if (mat.group(1).equals(HARDWARECORRUPTED_STRING)) {
    229. hardwareCorruptSize = Long.parseLong(mat.group(2));
    230. } else if (mat.group(1).equals(HUGEPAGESTOTAL_STRING)) {
    231. hugePagesTotal = Long.parseLong(mat.group(2));
    232. } else if (mat.group(1).equals(HUGEPAGESIZE_STRING)) {
    233. hugePageSize = Long.parseLong(mat.group(2));
    234. }
    235. }
    236. str = in.readLine();
    237. }
    238. } catch (IOException io) {
    239. LOG.warn("Error reading the stream " + io);
    240. } finally {
    241. //关闭流
    242. try {
    243. fReader.close();
    244. try {
    245. in.close();
    246. } catch (IOException i) {
    247. LOG.warn("Error closing the stream " + in);
    248. }
    249. } catch (IOException i) {
    250. LOG.warn("Error closing the stream " + fReader);
    251. }
    252. }
    253. readMemInfoFile = true;
    254. }
    255. /**
    256. * 读 /proc/cpuinfo, 解析和计算CPU信息.
    257. */
    258. private void readProcCpuInfoFile() {
    259. // 此目录只需读取一次
    260. if (readCpuInfoFile) {
    261. return;
    262. }
    263. HashSet coreIdSet = new HashSet<>();
    264. // Read "/proc/cpuinfo" file
    265. BufferedReader in;
    266. InputStreamReader fReader;
    267. try {
    268. fReader = new InputStreamReader(
    269. new FileInputStream(procfsCpuFile), Charset.forName("UTF-8"));
    270. in = new BufferedReader(fReader);
    271. } catch (FileNotFoundException f) {
    272. // shouldn't happen....
    273. LOG.warn("Couldn't read " + procfsCpuFile + "; can't determine cpu info");
    274. return;
    275. }
    276. Matcher mat;
    277. try {
    278. numProcessors = 0;
    279. numCores = 1;
    280. String currentPhysicalId = "";
    281. String str = in.readLine();
    282. while (str != null) {
    283. mat = PROCESSOR_FORMAT.matcher(str);
    284. if (mat.find()) {
    285. numProcessors++;
    286. }
    287. mat = FREQUENCY_FORMAT.matcher(str);
    288. if (mat.find()) {
    289. cpuFrequency = (long)(Double.parseDouble(mat.group(1)) * 1000); // kHz
    290. }
    291. mat = PHYSICAL_ID_FORMAT.matcher(str);
    292. if (mat.find()) {
    293. currentPhysicalId = str;
    294. }
    295. mat = CORE_ID_FORMAT.matcher(str);
    296. if (mat.find()) {
    297. coreIdSet.add(currentPhysicalId + " " + str);
    298. numCores = coreIdSet.size();
    299. }
    300. str = in.readLine();
    301. }
    302. } catch (IOException io) {
    303. LOG.warn("Error reading the stream " + io);
    304. } finally {
    305. // Close the streams
    306. try {
    307. fReader.close();
    308. try {
    309. in.close();
    310. } catch (IOException i) {
    311. LOG.warn("Error closing the stream " + in);
    312. }
    313. } catch (IOException i) {
    314. LOG.warn("Error closing the stream " + fReader);
    315. }
    316. }
    317. readCpuInfoFile = true;
    318. }
    319. /**
    320. * 读/proc/stat file, parse and calculate cumulative CPU.
    321. */
    322. private void readProcStatFile() {
    323. // Read "/proc/stat" file
    324. BufferedReader in;
    325. InputStreamReader fReader;
    326. try {
    327. fReader = new InputStreamReader(
    328. new FileInputStream(procfsStatFile), Charset.forName("UTF-8"));
    329. in = new BufferedReader(fReader);
    330. } catch (FileNotFoundException f) {
    331. // shouldn't happen....
    332. return;
    333. }
    334. Matcher mat;
    335. try {
    336. String str = in.readLine();
    337. while (str != null) {
    338. mat = CPU_TIME_FORMAT.matcher(str);
    339. if (mat.find()) {
    340. long uTime = Long.parseLong(mat.group(1));
    341. long nTime = Long.parseLong(mat.group(2));
    342. long sTime = Long.parseLong(mat.group(3));
    343. cpuTimeTracker.updateElapsedJiffies(
    344. BigInteger.valueOf(uTime + nTime + sTime),
    345. getCurrentTime());
    346. break;
    347. }
    348. str = in.readLine();
    349. }
    350. } catch (IOException io) {
    351. LOG.warn("Error reading the stream " + io);
    352. } finally {
    353. // Close the streams
    354. try {
    355. fReader.close();
    356. try {
    357. in.close();
    358. } catch (IOException i) {
    359. LOG.warn("Error closing the stream " + in);
    360. }
    361. } catch (IOException i) {
    362. LOG.warn("Error closing the stream " + fReader);
    363. }
    364. }
    365. }
    366. /**
    367. * Read /proc/net/dev file, 解析并计算通过网络读取和写入的字节数。
    368. */
    369. private void readProcNetInfoFile() {
    370. numNetBytesRead = 0L;
    371. numNetBytesWritten = 0L;
    372. // Read "/proc/net/dev" file
    373. BufferedReader in;
    374. InputStreamReader fReader;
    375. try {
    376. fReader = new InputStreamReader(
    377. new FileInputStream(procfsNetFile), Charset.forName("UTF-8"));
    378. in = new BufferedReader(fReader);
    379. } catch (FileNotFoundException f) {
    380. return;
    381. }
    382. Matcher mat;
    383. try {
    384. String str = in.readLine();
    385. while (str != null) {
    386. mat = PROCFS_NETFILE_FORMAT.matcher(str);
    387. if (mat.find()) {
    388. assert mat.groupCount() >= 16;
    389. // 忽略环回接口
    390. if (mat.group(1).equals("lo")) {
    391. str = in.readLine();
    392. continue;
    393. }
    394. numNetBytesRead += Long.parseLong(mat.group(2));
    395. numNetBytesWritten += Long.parseLong(mat.group(10));
    396. }
    397. str = in.readLine();
    398. }
    399. } catch (IOException io) {
    400. LOG.warn("Error reading the stream " + io);
    401. } finally {
    402. // Close the streams
    403. try {
    404. fReader.close();
    405. try {
    406. in.close();
    407. } catch (IOException i) {
    408. LOG.warn("Error closing the stream " + in);
    409. }
    410. } catch (IOException i) {
    411. LOG.warn("Error closing the stream " + fReader);
    412. }
    413. }
    414. }
    415. /**
    416. * Read /proc/diskstats file, 解析和计算从磁盘读取和写入磁盘的字节数。
    417. */
    418. private void readProcDisksInfoFile() {
    419. numDisksBytesRead = 0L;
    420. numDisksBytesWritten = 0L;
    421. // Read "/proc/diskstats" file
    422. BufferedReader in;
    423. try {
    424. in = new BufferedReader(new InputStreamReader(
    425. new FileInputStream(procfsDisksFile), Charset.forName("UTF-8")));
    426. } catch (FileNotFoundException f) {
    427. return;
    428. }
    429. Matcher mat;
    430. try {
    431. String str = in.readLine();
    432. while (str != null) {
    433. mat = PROCFS_DISKSFILE_FORMAT.matcher(str);
    434. if (mat.find()) {
    435. String diskName = mat.group(4);
    436. assert diskName != null;
    437. // 忽略循环或ram分区
    438. if (diskName.contains("loop") || diskName.contains("ram")) {
    439. str = in.readLine();
    440. continue;
    441. }
    442. Integer sectorSize;
    443. synchronized (perDiskSectorSize) {
    444. sectorSize = perDiskSectorSize.get(diskName);
    445. if (null == sectorSize) {
    446. // 检索扇区大小
    447. // 如果不可用或错误,假设512
    448. sectorSize = readDiskBlockInformation(diskName, 512);
    449. perDiskSectorSize.put(diskName, sectorSize);
    450. }
    451. }
    452. String sectorsRead = mat.group(7);
    453. String sectorsWritten = mat.group(11);
    454. if (null == sectorsRead || null == sectorsWritten) {
    455. return;
    456. }
    457. numDisksBytesRead += Long.parseLong(sectorsRead) * sectorSize;
    458. numDisksBytesWritten += Long.parseLong(sectorsWritten) * sectorSize;
    459. }
    460. str = in.readLine();
    461. }
    462. } catch (IOException e) {
    463. LOG.warn("Error reading the stream " + procfsDisksFile, e);
    464. } finally {
    465. // Close the streams
    466. try {
    467. in.close();
    468. } catch (IOException e) {
    469. LOG.warn("Error closing the stream " + procfsDisksFile, e);
    470. }
    471. }
    472. }
    473. /**
    474. * Read /sys/block/diskName/queue/hw_sector_size file, 解析并计算特定磁盘的扇区大小
    475. * @return sector size of specified disk, or defSector
    476. */
    477. int readDiskBlockInformation(String diskName, int defSector) {
    478. assert perDiskSectorSize != null && diskName != null;
    479. String procfsDiskSectorFile =
    480. "/sys/block/" + diskName + "/queue/hw_sector_size";
    481. BufferedReader in;
    482. try {
    483. in = new BufferedReader(new InputStreamReader(
    484. new FileInputStream(procfsDiskSectorFile),
    485. Charset.forName("UTF-8")));
    486. } catch (FileNotFoundException f) {
    487. return defSector;
    488. }
    489. Matcher mat;
    490. try {
    491. String str = in.readLine();
    492. while (str != null) {
    493. mat = PROCFS_DISKSECTORFILE_FORMAT.matcher(str);
    494. if (mat.find()) {
    495. String secSize = mat.group(1);
    496. if (secSize != null) {
    497. return Integer.parseInt(secSize);
    498. }
    499. }
    500. str = in.readLine();
    501. }
    502. return defSector;
    503. } catch (IOException|NumberFormatException e) {
    504. LOG.warn("Error reading the stream " + procfsDiskSectorFile, e);
    505. return defSector;
    506. } finally {
    507. // Close the streams
    508. try {
    509. in.close();
    510. } catch (IOException e) {
    511. LOG.warn("Error closing the stream " + procfsDiskSectorFile, e);
    512. }
    513. }
    514. }
    515. /** {@inheritDoc} */
    516. @Override
    517. public long getPhysicalMemorySize() {
    518. readProcMemInfoFile();
    519. return (ramSize
    520. - hardwareCorruptSize
    521. - (hugePagesTotal * hugePageSize)) * 1024;
    522. }
    523. /** {@inheritDoc} */
    524. @Override
    525. public long getVirtualMemorySize() {
    526. return getPhysicalMemorySize() + (swapSize * 1024);
    527. }
    528. /** {@inheritDoc} */
    529. @Override
    530. public long getAvailablePhysicalMemorySize() {
    531. readProcMemInfoFile(true);
    532. long inactive = inactiveFileSize != -1
    533. ? inactiveFileSize
    534. : inactiveSize;
    535. return (ramSizeFree + inactive) * 1024;
    536. }
    537. /** {@inheritDoc} */
    538. @Override
    539. public long getAvailableVirtualMemorySize() {
    540. return getAvailablePhysicalMemorySize() + (swapSizeFree * 1024);
    541. }
    542. /** {@inheritDoc} */
    543. @Override
    544. public int getNumProcessors() {
    545. readProcCpuInfoFile();
    546. return numProcessors;
    547. }
    548. /** {@inheritDoc} */
    549. @Override
    550. public int getNumCores() {
    551. readProcCpuInfoFile();
    552. return numCores;
    553. }
    554. /** {@inheritDoc} */
    555. @Override
    556. public long getCpuFrequency() {
    557. readProcCpuInfoFile();
    558. return cpuFrequency;
    559. }
    560. /** {@inheritDoc} */
    561. @Override
    562. public long getCumulativeCpuTime() {
    563. readProcStatFile();
    564. return cpuTimeTracker.getCumulativeCpuTime();
    565. }
    566. /** {@inheritDoc} */
    567. @Override
    568. public float getCpuUsagePercentage() {
    569. readProcStatFile();
    570. float overallCpuUsage = cpuTimeTracker.getCpuTrackerUsagePercent();
    571. if (overallCpuUsage != CpuTimeTracker.UNAVAILABLE) {
    572. overallCpuUsage = overallCpuUsage / getNumProcessors();
    573. }
    574. return overallCpuUsage;
    575. }
    576. /** {@inheritDoc} */
    577. @Override
    578. public float getNumVCoresUsed() {
    579. readProcStatFile();
    580. float overallVCoresUsage = cpuTimeTracker.getCpuTrackerUsagePercent();
    581. if (overallVCoresUsage != CpuTimeTracker.UNAVAILABLE) {
    582. overallVCoresUsage = overallVCoresUsage / 100F;
    583. }
    584. return overallVCoresUsage;
    585. }
    586. /** {@inheritDoc} */
    587. @Override
    588. public long getNetworkBytesRead() {
    589. readProcNetInfoFile();
    590. return numNetBytesRead;
    591. }
    592. /** {@inheritDoc} */
    593. @Override
    594. public long getNetworkBytesWritten() {
    595. readProcNetInfoFile();
    596. return numNetBytesWritten;
    597. }
    598. @Override
    599. public long getStorageBytesRead() {
    600. readProcDisksInfoFile();
    601. return numDisksBytesRead;
    602. }
    603. @Override
    604. public long getStorageBytesWritten() {
    605. readProcDisksInfoFile();
    606. return numDisksBytesWritten;
    607. }
    608. /**
    609. * 测试 {@link SysInfoLinux}.
    610. *
    611. * @param args - arguments to this calculator test
    612. */
    613. public static void main(String[] args) {
    614. SysInfoLinux plugin = new SysInfoLinux();
    615. System.out.println("Physical memory Size (bytes) : "
    616. + plugin.getPhysicalMemorySize());
    617. System.out.println("Total Virtual memory Size (bytes) : "
    618. + plugin.getVirtualMemorySize());
    619. System.out.println("Available Physical memory Size (bytes) : "
    620. + plugin.getAvailablePhysicalMemorySize());
    621. System.out.println("Total Available Virtual memory Size (bytes) : "
    622. + plugin.getAvailableVirtualMemorySize());
    623. System.out.println("Number of Processors : " + plugin.getNumProcessors());
    624. System.out.println("CPU frequency (kHz) : " + plugin.getCpuFrequency());
    625. System.out.println("Cumulative CPU time (ms) : " +
    626. plugin.getCumulativeCpuTime());
    627. System.out.println("Total network read (bytes) : "
    628. + plugin.getNetworkBytesRead());
    629. System.out.println("Total network written (bytes) : "
    630. + plugin.getNetworkBytesWritten());
    631. System.out.println("Total storage read (bytes) : "
    632. + plugin.getStorageBytesRead());
    633. System.out.println("Total storage written (bytes) : "
    634. + plugin.getStorageBytesWritten());
    635. try {
    636. // 睡眠,以便计算CPU使用量
    637. Thread.sleep(500L);
    638. } catch (InterruptedException e) {
    639. // do nothing
    640. }
    641. System.out.println("CPU usage % : " + plugin.getCpuUsagePercentage());
    642. }
    643. @VisibleForTesting
    644. void setReadCpuInfoFile(boolean readCpuInfoFileValue) {
    645. this.readCpuInfoFile = readCpuInfoFileValue;
    646. }
    647. public long getJiffyLengthInMillis() {
    648. return this.jiffyLengthInMillis;
    649. }
    650. }

    从源码中可以看到,linux上的资源信息是从各个文件中获取的:

    /proc/meminfo    解析和计算内存信息
    /proc/cpuinfo    解析和计算CPU信息
    /proc/stat        获取CPU的运行数据
    /proc/net/dev    解析并计算通过网络读取和写入的字节数。
    /proc/diskstats    解析和计算从磁盘读取和写入磁盘的字节数
    /sys/block/partition_name/queue/hw_sector_size 解析并计算特定磁盘的扇区大小

    下面我们看下linux操作系统中的这些文件中都是什么内容

    三、proc下各示例文件

    1、/proc/meminfo

    MemTotal:       131479404 kB 
    MemFree:        29109144 kB
    MemAvailable:   109564132 kB
    Buffers:         3922940 kB
    Cached:         65545372 kB
    SwapCached:            0 kB
    Active:          9252304 kB
    Inactive:       79107168 kB
    Active(anon):     120256 kB
    Inactive(anon): 18893260 kB
    Active(file):    9132048 kB
    Inactive(file): 60213908 kB
    Unevictable:           0 kB
    Mlocked:               0 kB
    SwapTotal:             0 kB
    SwapFree:              0 kB
    Dirty:            123956 kB
    Writeback:             0 kB
    AnonPages:      18856940 kB
    Mapped:           151268 kB
    Shmem:            122260 kB
    KReclaimable:   12166144 kB
    Slab:           13454424 kB
    SReclaimable:   12166144 kB
    SUnreclaim:      1288280 kB
    KernelStack:       29584 kB
    PageTables:        88028 kB
    NFS_Unstable:          0 kB
    Bounce:                0 kB
    WritebackTmp:          0 kB
    CommitLimit:    65739700 kB
    Committed_AS:   34508552 kB
    VmallocTotal:   34359738367 kB
    VmallocUsed:      168540 kB
    VmallocChunk:          0 kB
    Percpu:           210432 kB
    HardwareCorrupted:     0 kB
    AnonHugePages:  12728320 kB
    ShmemHugePages:        0 kB
    ShmemPmdMapped:        0 kB
    FileHugePages:         0 kB
    FilePmdMapped:         0 kB
    DupText:               0 kB
    HugePages_Total:       0
    HugePages_Free:        0
    HugePages_Rsvd:        0
    HugePages_Surp:        0
    Hugepagesize:       2048 kB
    Hugetlb:               0 kB
    DirectMap4k:     2277228 kB
    DirectMap2M:    119357440 kB
    DirectMap1G:    14680064 kB

    /proc/meminfo是了解Linux系统内存使用状况的主要接口,我们最常用的”free”、”vmstat”等命令就是通过它获取数据的

    MemTotal:系统从加电开始到引导完成,firmware/BIOS要保留一些内存,kernel本身要占用一些内存,最后剩下可供kernel支配的内存就是MemTotal。这个值在系统运行期间一般是固定不变的

    MemFree:表示系统尚未使用的内存。[MemTotal-MemFree]就是已被用掉的内存

    MemAvailable:有些应用程序会根据系统的可用内存大小自动调整内存申请的多少,所以需要一个记录当前可用内存数量的统计值,MemFree并不适用,因为MemFree不能代表全部可用的内存,系统中有些内存虽然已被使用但是可以回收的,比如cache/buffer、slab都有一部分可以回收,所以这部分可回收的内存加上MemFree才是系统可用的内存,即MemAvailable。/proc/meminfo中的MemAvailable是内核使用特定的算法估算出来的,要注意这是一个估计值,并不精确

    Buffers:用于缓存数据的内存量

    Cached:用于缓存文件系统数据的内存量

    SwapCached:用于缓存交换分区数据的内存量

    Active:活跃内存量,活跃指最近被访问过或正在使用中的内存

    Inactive:非活跃内存量,非活跃指长时间没有被访问或已经释放但仍在缓冲区中的内存

    Active(anon):活跃的匿名内存

    Inactive(anon):不活跃的匿名内存

    Active(file):活跃的文件使用内存

    Inactive(file):不活跃的文件使用内存

    Unevictable:不能被释放的内存页

    Mlocked:系统调用 mlock 家族允许程序在物理内存上锁住它的部分或全部地址空间。这将阻止Linux 将这个内存页调度到交换空间(swap space),即使该程序已有一段时间没有访问这段空间

    SwapTotal:交换分区总容量

    SwapFree:交换分区剩余容量

    Dirty:脏页面数量,脏页面是指已经被修改但还没有被写回磁盘的页面

    Writeback:等待写回磁盘的页面数量

    AnonPages:未映射页的内存大小

    Mapped:设备和文件等映射的大小

    Shmem:包含共享内存以及tmpfs文件系统占用的内存

    KReclaimable:SReclaimable的基础上加上MISC_RECLAIMABLE

    Slab:Slab是Linux中用来管理小块内核对象分配和释放的一种内存管理机制,Slab = SReclaimable + SUnreclaim

    SReclaimable:slab中可回收的部分

    SUnreclaim:slab中不可回收的部分

    KernelStack:内核消耗的内存

    PageTables:管理内存分页的索引表的大小

    NFS_Unstable:不稳定页表的大小

    Bounce:在低端内存中分配一个临时buffer作为跳转,把位于高端内存的缓存数据复制到此处消耗的内存

    WritebackTmp:FUSE用于临时写回缓冲区的内存

    CommitLimit:系统实际可分配内存

    Committed_AS:系统当前已分配的内存

    VmallocTotal:预留的虚拟内存总量

    VmallocUsed:已经被使用的虚拟内存

    VmallocChunk:可分配的最大的逻辑连续的虚拟内存

    Percpu:表示用于percpu分配的的内存大小,不包括metadata

    HardwareCorrupted:当系统检测到内存的硬件故障时删除掉的内存页的总量

    AnonHugePages:匿名大页缓存

    ShmemHugePages:表示用于shared memory或tmpfs的透明大页

    ShmemPmdMapped:表示用于用户态shared memory映射的透明大页

    FileHugePages:

    FilePmdMapped:

    DupText:

    HugePages_Total:预留的大页内存总量

    HugePages_Free:空闲的大页内存

    HugePages_Rsvd:已经被应用程序分配但尚未使用的大页内存

    HugePages_Surp:初始大页数与修改配置后大页数的差值

    Hugepagesize:单个大页内存的大小

    Hugetlb:

    DirectMap4k:映射TLB为4kB的内存数量

    DirectMap2M:映射TLB为2M的内存数量

    DirectMap1G:映射TLB为1G的内存数量

    2、/proc/cpuinfo

    processor       : 0
    vendor_id       : GenuineIntel
    cpu family      : 6
    model           : 85
    model name      : Intel Xeon Processor (Skylake, IBRS)
    stepping        : 4
    microcode       : 0x1
    cpu MHz         : 2299.992
    cache size      : 16384 KB
    physical id     : 0
    siblings        : 12
    core id         : 0
    cpu cores       : 12
    apicid          : 0
    initial apicid  : 0
    fpu             : yes
    fpu_exception   : yes
    cpuid level     : 13
    wp              : yes
    flags           : fpu vme de pse tsc msr pae mce cx8 apic sep mtrr pge mca cmov pat pse36 clflush mmx fxsr sse sse2 ss ht syscall nx pdpe1gb rdtscp lm constant_tsc rep_good nopl xtopology c
    puid tsc_known_freq pni pclmulqdq ssse3 fma cx16 pcid sse4_1 sse4_2 x2apic movbe popcnt tsc_deadline_timer aes xsave avx f16c rdrand hypervisor lahf_lm abm 3dnowprefetch cpuid_fault invpcid
    _single ssbd ibrs ibpb stibp fsgsbase tsc_adjust bmi1 hle avx2 smep bmi2 erms invpcid rtm mpx avx512f avx512dq rdseed adx smap clflushopt clwb avx512cd avx512bw avx512vl xsaveopt xsavec xge
    tbv1 xsaves arat umip pku ospke md_clear
    bugs            : cpu_meltdown spectre_v1 spectre_v2 spec_store_bypass l1tf mds swapgs taa itlb_multihit mmio_stale_data retbleed
    bogomips        : 4599.98
    clflush size    : 64
    cache_alignment : 64
    address sizes   : 46 bits physical, 48 bits virtual
    power management:

    .................................省略...............................

    processor       : 23
    vendor_id       : GenuineIntel
    cpu family      : 6
    model           : 85
    model name      : Intel Xeon Processor (Skylake, IBRS)
    stepping        : 4
    microcode       : 0x1
    cpu MHz         : 2299.992
    cache size      : 16384 KB
    physical id     : 1
    siblings        : 12
    core id         : 11
    cpu cores       : 12
    apicid          : 27
    initial apicid  : 27
    fpu             : yes
    fpu_exception   : yes
    cpuid level     : 13
    wp              : yes
    flags           : fpu vme de pse tsc msr pae mce cx8 apic sep mtrr pge mca cmov pat pse36 clflush mmx fxsr sse sse2 ss ht syscall nx pdpe1gb rdtscp lm constant_tsc rep_good nopl xtopology cpuid tsc_known_freq pni pclmulqdq ssse3 fma cx16 pcid sse4_1 sse4_2 x2apic movbe popcnt tsc_deadline_timer aes xsave avx f16c rdrand hypervisor lahf_lm abm 3dnowprefetch cpuid_fault invpcid_single ssbd ibrs ibpb stibp fsgsbase tsc_adjust bmi1 hle avx2 smep bmi2 erms invpcid rtm mpx avx512f avx512dq rdseed adx smap clflushopt clwb avx512cd avx512bw avx512vl xsaveopt xsavec xgetbv1 xsaves arat umip pku ospke md_clear
    bugs            : cpu_meltdown spectre_v1 spectre_v2 spec_store_bypass l1tf mds swapgs taa itlb_multihit mmio_stale_data retbleed
    bogomips        : 4599.98
    clflush size    : 64
    cache_alignment : 64
    address sizes   : 46 bits physical, 48 bits virtual
    power management:

    通过/proc/cpuinfo,可以查看系统中CPU的提供商和相关配置信息,例如我们想获取,有多少颗物理CPU,每个物理cpu核心数,以及超线程是否开启等信息,下面是每项参数的解释:

    processor :系统中逻辑处理核心数的编号,从0开始排序

    vendor_id :CPU制造商

    cpu family :CPU产品系列代号

    model :CPU属于其系列中的哪一代的代号

    model name:CPU属于的名字及其编号、标称主频

    stepping  :CPU属于制作更新版本

    cpu MHz  :CPU的实际使用主频

    cache size :CPU二级缓存大小

    physical id :单个物理CPU的标号

    siblings :单个物理CPU的逻辑CPU数。siblings=cpu cores [*2]

    core id :当前物理核在其所处CPU中的编号,这个编号不一定连续

    cpu cores :该逻辑核所处CPU的物理核数。比如此处cpu cores 是4个,那么对应core id 可能是 1、3、4、5。

    apicid :用来区分不同逻辑核的编号,系统中每个逻辑核的此编号必然不同,此编号不一定连续

    fpu :是否具有浮点运算单元(Floating Point Unit)

    fpu_exception :是否支持浮点计算异常

    cpuid level :执行cpuid指令前,eax寄存器中的值,根据不同的值cpuid指令会返回不同的内容

    wp :表明当前CPU是否在内核态支持对用户空间的写保护(Write Protection)

    flags :当前CPU支持的功能

    bugs :保存内核检测到的硬件错误

    bogomips:在系统内核启动时粗略测算的CPU速度(Million Instructions Per Second

    clflush size :每次刷新缓存的大小单位

    cache_alignment :缓存地址对齐单位

    address sizes :可访问地址空间位数

    power management :对能源管理的支持

    3、/proc/stat

    cpu  8736131408 5678 193273561 20516569092 64420147 202089758 24839900 736849109 0 0
    cpu0 248135539 221 7727953 977102347 3547852 7843342 1836321 26959080 0 0
    cpu1 288960610 208 7253118 939752913 3465875 6253758 983012 22610655 0 0
    cpu2 331782665 173 6580943 898614791 3179773 5927649 705463 20377701 0 0
    cpu3 357312958 119 6079401 873515056 3082820 5636253 675032 19192651 0 0
    cpu4 416415379 134 4970987 817517624 2702326 5029001 461878 15707695 0 0
    cpu5 431656991 49 4560783 803250964 2571613 4865074 410522 14757252 0 0
    cpu6 435254195 169 4473639 799793313 2533305 4816086 391800 14568012 0 0
    cpu7 430149966 193 5306474 799970897 2274711 5119291 4203530 15644401 0 0
    cpu8 442943177 38 4245770 792483084 2429873 4720225 472371 14247201 0 0
    cpu9 450045462 66 4306296 784947171 2410185 4660788 1014418 13736325 0 0
    cpu10 451355787 39 4064980 784676208 2261500 4619102 396365 13709422 0 0
    cpu11 457452811 64 3901559 778822656 2231050 4565301 393815 13362096 0 0
    cpu12 308242715 360 10256742 887773491 2996516 16295533 1139546 52646450 0 0
    cpu13 291977604 326 12356349 906520116 2948164 14127718 995623 49241553 0 0
    cpu14 314799511 763 11789179 887439430 2724265 12548004 926359 45887607 0 0
    cpu15 343893959 589 10565703 861975365 2476760 11234089 879714 42636791 0 0
    cpu16 357686825 202 9889055 850148237 2299417 10596337 839523 40920853 0 0
    cpu17 371250803 336 9230196 838222800 2170862 10053101 814107 39442271 0 0
    cpu18 381559924 227 8684083 829076848 2133621 9640147 793837 38300080 0 0
    cpu19 391204359 360 8217143 820527206 2044874 9294489 780223 37347635 0 0
    cpu20 395787749 376 7934865 816504952 2030798 9101060 793620 36768582 0 0
    cpu21 382765684 287 8586382 826536768 2751789 9517617 1313220 39011440 0 0
    cpu22 403637541 284 7699240 808560612 3025058 8623423 868515 35789081 0 0
    cpu23 51859181 83 24592711 1132836231 4127127 17002359 2751076 73984264 0 0
    intr 41293626138 0 9 0 0 250 0 0 0 0 0 1257757 0 15 0 12281947 0 0 0 0 0 0 0 0 0 0 74418226 0 9915152 0 62205235 0 16892400 0 170973248 4915 0 3076909346 41960 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
    ctxt 66125412027
    btime 1695643289
    processes 68123558
    procs_running 20
    procs_blocked 0
    softirq 26896249797 0 1534546890 2296517 681491783 147607814 0 4570937 2751393260 9053148 290452968

    /proc/stat记录的是系统进程整体的统计信息

    cpu ~ cpu23 描述的指标如下:(单位都是jiffies,1jiffies=0.01秒)

    nameusernicesystemidleiowaitirrqsoftirqstealguestguest_nice
    cpu8736131408567819327356120516569092644201472020897582483990073684910900
    …………………………………………………………
    cpu23518591818324592711113283623141271271700235927510767398426400

    这部分统计了CPU时间消耗分布在哪些地方,是用户态任务,还是内核或者是中断、idle等等;第一行的第一个字段为"cpu",没有指定CPU号,表示是其他各个CPU时间分布的汇总;而其他行有cpu编号表示特定编号的cpu时间消耗分布情况。

    name:cpu汇总/cpu编号

    user:到目前为止,CPU上nice值不大于0的用户态任务的运行时间

    nice:到目前为止,CPU上nice值大于0的用户态任务的运行时间

    system:到目前为止,CPU上内核态的运行时间。包括用户态任务系统调用、异常等陷入内核消耗时间,也包括内核线程消耗的时间; 但是不包括中断和软中断的执行时间

    idle:到目前为止,处于idle任务的时间。不包括CPU上因为任务IO阻塞导致CPU上没有任务可运行、处于idle状态的时间。

    iowait:到目前为止,由于CPU上任务IO阻塞导致CPU无可运行任务、处于idle的时间。需要强调的是,iowait是在CPU处于idle状态下的一种特殊情况的时间,与上面的“idle”列互补构成CPU上真正处于idle的时间。

    irrq:到目前为止,CPU进入到中断处理的时间(在没有使能CONFIG_IRQ_TIME_ACCOUNTING的情况下,大部分架构实际上无法记录到该项,见下面的分析)。

    softirq:到目前为止,CPU处理软中断的时间,包括softirqd中处理软中断的时间。

    steal:与虚拟化有关

    guest:与虚拟化有关

    guest_nice:与虚拟化有关

    其他指标如下:

    intr:系统启动以来的所有interrupts的次数情况

    ctxt: 系统上下文切换次数

    btime:启动时长(单位:秒),从Epoch(即1970零时)开始到系统启动所经过的时长,每次启动会改变。此处指为1695643289,转换北京时间为2023-09-25 20:01:29

    processes:系统启动后所创建过的进程数量。当短时间该值特别大,系统可能出现异常

    procs_running:处于Runnable状态的进程个数

    procs_blocked:处于被阻塞的进程个数

    softirq:此行显示所有CPU的softirq总数,第一列是所有软件和每个软件的总数,后面的列是特定softirq的总数

    4、/proc/net/dev

    Inter-|   Receive                                                |  Transmit
     face |bytes    packets errs drop fifo frame compressed multicast|bytes    packets errs drop fifo colls carrier compressed
        lo: 8262570189990 1009625458    0 1217    0     0          0         0 8262570189990 1009625458    0    0    0     0       0          0
      eth0: 4725352845467 3727035213    0    0    0     0          0         0 12125473603784 322028286    0    0    0     0       0          0
      eth1: 12250497813726 9789277543    0 1066    0     0          0         0 12066904463831 2712923220    0    0    0     0       0          0

    /proc/net/dev提供了网络设备接口的统计信息,lo、eth0、eth1为网络社保接口的名称。下面是具体指标解释

    bytes:接收或发送的总字节数。

    packets:接收或发送的总数据包数量。

    errs:在接收或发送过程中发生的错误数量。

    drop:由于缓冲区溢出或其他原因而丢弃的数据包数量。

    fifo:由于队列拥塞而丢弃的数据包数量。

    frame:由于帧错误而丢弃的数据包数量。

    compressed:压缩传输所节省的字节数量。

    multicast:接收到多播数据包的数量。

    5、/proc/diskstats

     253       0 vda 978184 4128 81150594 20755299 73453182 4078455 1309816689 398292145 0 113223744 426791458 0 0 0 0 15585634 7744013 20200452 365556940 0
     253       1 vda1 977999 4128 81131978 20753990 72102739 4078455 1309816681 396863176 0 112567056 417617166 0 0 0 0 0 0 20199145 365556938 0
     253      16 vdb 10371383 566918 5197295816 186317736 4253043 5537854 2637106896 128050659 0 68754698 314653319 0 0 0 0 411815 284922 185895864 126318932 0
     253      17 vdb1 10371274 566918 5197280288 186316863 4253012 5537854 2637106896 128050617 0 68754916 314367481 0 0 0 0 0 0 185894994 126318932 0
     253      32 vdc 62355261 2902021 51036086962 4222776827 51209471 48829571 38641223240 1144000034 1 453445155 1073094954 0 0 0 0 1186448 1285388 4096018303 1082051035 0
      11       0 sr0 352 0 3115 420 0 0 0 0 0 456 420 0 0 0 0 0 0 419 0 0

    /proc/diskstatsv提供了磁盘信息的统计信息,含义从左到右依次如下

    设备号 编号 设备  读完成次数  合并完成次数   读扇区次数   读操作花费毫秒数   写完成次数   合并写完成次数   写扇区次数   写操作花费的毫秒数   正在处理的输入/输出请求数   输入/输出操作花费的毫秒数   输入/输出操作花费的加权毫秒数

    6、/sys/block/partition_name/queue/hw_sector_size

    通过hw_sector_size可以获取磁盘块大小相关的信息。我们把partition_name换成vda、vdb、vdc或者sr0即可,注意:下面的512就是文件的内容

    vda、vdb、vdc的磁盘块大小为

    512

    sr0的磁盘块大小为

    2048

  • 相关阅读:
    【TB作品】MSP430G2553,单片机,口袋板, 烘箱温度控制器
    微信小程序获取用户头像昵称组件封装(最新版)
    Vue-cli3 通过配置 public 目录下的 config.js 和config.json 实现一次编译,修改生效
    设计模式学习(三):工厂模式
    网上选课系统的设计与实现(ASP.NET)
    react-navigation学习
    嵌入式面试常见问题(一)
    【Leetcode刷题Python】416. 分割等和子集
    GPU性能优化与模型训练概览
    Lua脚本
  • 原文地址:https://blog.csdn.net/lu070828/article/details/136146608