github.com/u-root/u-root@v7.0.1-0.20200915234505-ad7babab0a8e+incompatible/cmds/core/free/free_linux.go (about) 1 // Copyright 2018 the u-root Authors. All rights reserved 2 // Use of this source code is governed by a BSD-style 3 // license that can be found in the LICENSE file. 4 5 package main 6 7 import ( 8 "bytes" 9 "fmt" 10 "io/ioutil" 11 "strconv" 12 ) 13 14 const meminfoFile = "/proc/meminfo" 15 16 // meminfo returns a mapping that represents the fields contained in 17 // /proc/meminfo 18 func meminfo() (meminfomap, error) { 19 buf, err := ioutil.ReadFile(meminfoFile) 20 if err != nil { 21 return nil, err 22 } 23 return meminfoFromBytes(buf) 24 } 25 26 // meminfoFromBytes returns a mapping that represents the fields contained in a 27 // byte stream with a content compatible with /proc/meminfo 28 func meminfoFromBytes(buf []byte) (meminfomap, error) { 29 ret := make(meminfomap) 30 for _, line := range bytes.Split(buf, []byte{'\n'}) { 31 kv := bytes.SplitN(line, []byte{':'}, 2) 32 if len(kv) != 2 { 33 // invalid line? 34 continue 35 } 36 key := string(kv[0]) 37 tokens := bytes.SplitN(bytes.TrimSpace(kv[1]), []byte{' '}, 2) 38 if len(tokens) > 0 { 39 value, err := strconv.ParseUint(string(tokens[0]), 10, 64) 40 if err != nil { 41 return nil, err 42 } 43 ret[key] = value 44 } 45 } 46 return ret, nil 47 } 48 49 // getMainMemInfo prints the physical memory information in the specified units. Only 50 // the relevant fields will be used from the input map. 51 func getMainMemInfo(m meminfomap, config *FreeConfig) (*mainMemInfo, error) { 52 fields := []string{ 53 "MemTotal", 54 "MemFree", 55 "Buffers", 56 "Cached", 57 "Shmem", 58 "SReclaimable", 59 "MemAvailable", 60 } 61 if missingRequiredFields(m, fields) { 62 return nil, fmt.Errorf("missing required fields from meminfo") 63 } 64 65 // These values are expressed in kibibytes, convert to the desired unit 66 memTotal := m["MemTotal"] << KB 67 memFree := m["MemFree"] << KB 68 memShared := m["Shmem"] << KB 69 memCached := (m["Cached"] + m["SReclaimable"]) << KB 70 memBuffers := (m["Buffers"]) << KB 71 memUsed := memTotal - memFree - memCached - memBuffers 72 memAvailable := m["MemAvailable"] << KB 73 74 mmi := mainMemInfo{ 75 Total: memTotal, 76 Used: memUsed, 77 Free: memFree, 78 Shared: memShared, 79 Cached: memCached, 80 Buffers: memBuffers, 81 Available: memAvailable, 82 } 83 return &mmi, nil 84 } 85 86 // getSwapInfo prints the swap space information in the specified units. Only the 87 // relevant fields will be used from the input map. 88 func getSwapInfo(m meminfomap, config *FreeConfig) (*swapInfo, error) { 89 fields := []string{ 90 "SwapTotal", 91 "SwapFree", 92 } 93 if missingRequiredFields(m, fields) { 94 return nil, fmt.Errorf("missing required fields from meminfo") 95 } 96 // These values are expressed in kibibytes, convert to the desired unit 97 swapTotal := m["SwapTotal"] << KB 98 swapUsed := (m["SwapTotal"] - m["SwapFree"]) << KB 99 swapFree := m["SwapFree"] << KB 100 101 si := swapInfo{ 102 Total: swapTotal, 103 Used: swapUsed, 104 Free: swapFree, 105 } 106 return &si, nil 107 }