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  }