1
0

mem_linux.go 3.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158
  1. // +build linux
  2. package mem
  3. import (
  4. "context"
  5. "strconv"
  6. "strings"
  7. "github.com/shirou/gopsutil/internal/common"
  8. "golang.org/x/sys/unix"
  9. )
  10. func VirtualMemory() (*VirtualMemoryStat, error) {
  11. return VirtualMemoryWithContext(context.Background())
  12. }
  13. func VirtualMemoryWithContext(ctx context.Context) (*VirtualMemoryStat, error) {
  14. filename := common.HostProc("meminfo")
  15. lines, _ := common.ReadLines(filename)
  16. // flag if MemAvailable is in /proc/meminfo (kernel 3.14+)
  17. memavail := false
  18. ret := &VirtualMemoryStat{}
  19. for _, line := range lines {
  20. fields := strings.Split(line, ":")
  21. if len(fields) != 2 {
  22. continue
  23. }
  24. key := strings.TrimSpace(fields[0])
  25. value := strings.TrimSpace(fields[1])
  26. value = strings.Replace(value, " kB", "", -1)
  27. t, err := strconv.ParseUint(value, 10, 64)
  28. if err != nil {
  29. return ret, err
  30. }
  31. switch key {
  32. case "MemTotal":
  33. ret.Total = t * 1024
  34. case "MemFree":
  35. ret.Free = t * 1024
  36. case "MemAvailable":
  37. memavail = true
  38. ret.Available = t * 1024
  39. case "Buffers":
  40. ret.Buffers = t * 1024
  41. case "Cached":
  42. ret.Cached = t * 1024
  43. case "Active":
  44. ret.Active = t * 1024
  45. case "Inactive":
  46. ret.Inactive = t * 1024
  47. case "Writeback":
  48. ret.Writeback = t * 1024
  49. case "WritebackTmp":
  50. ret.WritebackTmp = t * 1024
  51. case "Dirty":
  52. ret.Dirty = t * 1024
  53. case "Shmem":
  54. ret.Shared = t * 1024
  55. case "Slab":
  56. ret.Slab = t * 1024
  57. case "SReclaimable":
  58. ret.SReclaimable = t * 1024
  59. case "PageTables":
  60. ret.PageTables = t * 1024
  61. case "SwapCached":
  62. ret.SwapCached = t * 1024
  63. case "CommitLimit":
  64. ret.CommitLimit = t * 1024
  65. case "Committed_AS":
  66. ret.CommittedAS = t * 1024
  67. case "HighTotal":
  68. ret.HighTotal = t * 1024
  69. case "HighFree":
  70. ret.HighFree = t * 1024
  71. case "LowTotal":
  72. ret.LowTotal = t * 1024
  73. case "LowFree":
  74. ret.LowFree = t * 1024
  75. case "SwapTotal":
  76. ret.SwapTotal = t * 1024
  77. case "SwapFree":
  78. ret.SwapFree = t * 1024
  79. case "Mapped":
  80. ret.Mapped = t * 1024
  81. case "VmallocTotal":
  82. ret.VMallocTotal = t * 1024
  83. case "VmallocUsed":
  84. ret.VMallocUsed = t * 1024
  85. case "VmallocChunk":
  86. ret.VMallocChunk = t * 1024
  87. case "HugePages_Total":
  88. ret.HugePagesTotal = t
  89. case "HugePages_Free":
  90. ret.HugePagesFree = t
  91. case "Hugepagesize":
  92. ret.HugePageSize = t * 1024
  93. }
  94. }
  95. ret.Cached += ret.SReclaimable
  96. if !memavail {
  97. ret.Available = ret.Free + ret.Buffers + ret.Cached
  98. }
  99. ret.Used = ret.Total - ret.Free - ret.Buffers - ret.Cached
  100. ret.UsedPercent = float64(ret.Used) / float64(ret.Total) * 100.0
  101. return ret, nil
  102. }
  103. func SwapMemory() (*SwapMemoryStat, error) {
  104. return SwapMemoryWithContext(context.Background())
  105. }
  106. func SwapMemoryWithContext(ctx context.Context) (*SwapMemoryStat, error) {
  107. sysinfo := &unix.Sysinfo_t{}
  108. if err := unix.Sysinfo(sysinfo); err != nil {
  109. return nil, err
  110. }
  111. ret := &SwapMemoryStat{
  112. Total: uint64(sysinfo.Totalswap) * uint64(sysinfo.Unit),
  113. Free: uint64(sysinfo.Freeswap) * uint64(sysinfo.Unit),
  114. }
  115. ret.Used = ret.Total - ret.Free
  116. //check Infinity
  117. if ret.Total != 0 {
  118. ret.UsedPercent = float64(ret.Total-ret.Free) / float64(ret.Total) * 100.0
  119. } else {
  120. ret.UsedPercent = 0
  121. }
  122. filename := common.HostProc("vmstat")
  123. lines, _ := common.ReadLines(filename)
  124. for _, l := range lines {
  125. fields := strings.Fields(l)
  126. if len(fields) < 2 {
  127. continue
  128. }
  129. switch fields[0] {
  130. case "pswpin":
  131. value, err := strconv.ParseUint(fields[1], 10, 64)
  132. if err != nil {
  133. continue
  134. }
  135. ret.Sin = value * 4 * 1024
  136. case "pswpout":
  137. value, err := strconv.ParseUint(fields[1], 10, 64)
  138. if err != nil {
  139. continue
  140. }
  141. ret.Sout = value * 4 * 1024
  142. }
  143. }
  144. return ret, nil
  145. }