meminfo_linux.go 1.5 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970
  1. package system // import "github.com/docker/docker/pkg/system"
  2. import (
  3. "bufio"
  4. "io"
  5. "os"
  6. "strconv"
  7. "strings"
  8. )
  9. // ReadMemInfo retrieves memory statistics of the host system and returns a
  10. // MemInfo type.
  11. func ReadMemInfo() (*MemInfo, error) {
  12. file, err := os.Open("/proc/meminfo")
  13. if err != nil {
  14. return nil, err
  15. }
  16. defer file.Close()
  17. return parseMemInfo(file)
  18. }
  19. // parseMemInfo parses the /proc/meminfo file into
  20. // a MemInfo object given an io.Reader to the file.
  21. // Throws error if there are problems reading from the file
  22. func parseMemInfo(reader io.Reader) (*MemInfo, error) {
  23. meminfo := &MemInfo{}
  24. scanner := bufio.NewScanner(reader)
  25. memAvailable := int64(-1)
  26. for scanner.Scan() {
  27. // Expected format: ["MemTotal:", "1234", "kB"]
  28. parts := strings.Fields(scanner.Text())
  29. // Sanity checks: Skip malformed entries.
  30. if len(parts) < 3 || parts[2] != "kB" {
  31. continue
  32. }
  33. // Convert to bytes.
  34. size, err := strconv.Atoi(parts[1])
  35. if err != nil {
  36. continue
  37. }
  38. // Convert to KiB
  39. bytes := int64(size) * 1024
  40. switch parts[0] {
  41. case "MemTotal:":
  42. meminfo.MemTotal = bytes
  43. case "MemFree:":
  44. meminfo.MemFree = bytes
  45. case "MemAvailable:":
  46. memAvailable = bytes
  47. case "SwapTotal:":
  48. meminfo.SwapTotal = bytes
  49. case "SwapFree:":
  50. meminfo.SwapFree = bytes
  51. }
  52. }
  53. if memAvailable != -1 {
  54. meminfo.MemFree = memAvailable
  55. }
  56. // Handle errors that may have occurred during the reading of the file.
  57. if err := scanner.Err(); err != nil {
  58. return nil, err
  59. }
  60. return meminfo, nil
  61. }