//+build darwin package staros import ( "encoding/binary" "fmt" "golang.org/x/sys/unix" "os/exec" "strconv" "strings" "unsafe" ) // Memory 系统内存信息 func Memory() (MemStatus,error) { return darwinMemory() } type swapUsage struct { Total uint64 Avail uint64 Used uint64 Pagesize int32 Encrypted bool } func darwinMemory() (MemStatus, error) { var err error var res MemStatus vm_stat, err := exec.LookPath("vm_stat") if err != nil { return res, err } out, err := exec.Command(vm_stat).CombinedOutput() if err != nil { return res, err } totalString, err := unix.Sysctl("hw.memsize") if err != nil { return res, err } // unix.sysctl() helpfully assumes the result is a null-terminated string and // removes the last byte of the result if it's 0 :/ totalString += "\x00" res.All = uint64(binary.LittleEndian.Uint64([]byte(totalString))) lines := strings.Split(string(out), "\n") pagesize := uint64(unix.Getpagesize()) for _, line := range lines { fields := strings.Split(line, ":") if len(fields) < 2 { continue } key := strings.TrimSpace(fields[0]) value := strings.Trim(fields[1], " .") switch key { case "Pages free": free, e := strconv.ParseUint(value, 10, 64) if e != nil { err = e } res.Free = free * pagesize case "Pages inactive": inactive, e := strconv.ParseUint(value, 10, 64) if e != nil { err = e } res.Available = inactive * pagesize case "Pages active": active, e := strconv.ParseUint(value, 10, 64) if e != nil { err = e } _ = active * pagesize case "Pages wired down": wired, e := strconv.ParseUint(value, 10, 64) if e != nil { err = e } _ = wired * pagesize } } res.Available += res.Free res.Used = res.All - res.Available //swap value, err := unix.SysctlRaw("vm.swapusage") if err != nil { return res, err } if len(value) != 32 { return res, fmt.Errorf("unexpected output of sysctl vm.swapusage: %v (len: %d)", value, len(value)) } swap := (*swapUsage)(unsafe.Pointer(&value[0])) res.SwapAll = swap.Total res.SwapUsed = swap.Used res.SwapFree = swap.Avail return res, err }