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