...
1
2
3 package mem
4
5 import (
6 "context"
7 "errors"
8 "unsafe"
9
10 "golang.org/x/sys/unix"
11
12 "github.com/shirou/gopsutil/internal/common"
13 )
14
15 func VirtualMemory() (*VirtualMemoryStat, error) {
16 return VirtualMemoryWithContext(context.Background())
17 }
18
19 func VirtualMemoryWithContext(ctx context.Context) (*VirtualMemoryStat, error) {
20 pageSize, err := common.SysctlUint("vm.stats.vm.v_page_size")
21 if err != nil {
22 return nil, err
23 }
24 physmem, err := common.SysctlUint("hw.physmem")
25 if err != nil {
26 return nil, err
27 }
28
29 free, err := common.SysctlUint("vm.stats.vm.v_free_count")
30 if err != nil {
31 return nil, err
32 }
33 active, err := common.SysctlUint("vm.stats.vm.v_active_count")
34 if err != nil {
35 return nil, err
36 }
37 inactive, err := common.SysctlUint("vm.stats.vm.v_inactive_count")
38 if err != nil {
39 return nil, err
40 }
41 buffers, err := common.SysctlUint("vfs.bufspace")
42 if err != nil {
43 return nil, err
44 }
45 wired, err := common.SysctlUint("vm.stats.vm.v_wire_count")
46 if err != nil {
47 return nil, err
48 }
49 var cached, laundry uint64
50 osreldate, _ := common.SysctlUint("kern.osreldate")
51 if osreldate < 1102000 {
52 cached, err = common.SysctlUint("vm.stats.vm.v_cache_count")
53 if err != nil {
54 return nil, err
55 }
56 } else {
57 laundry, err = common.SysctlUint("vm.stats.vm.v_laundry_count")
58 if err != nil {
59 return nil, err
60 }
61 }
62
63 p := pageSize
64 ret := &VirtualMemoryStat{
65 Total: physmem,
66 Free: free * p,
67 Active: active * p,
68 Inactive: inactive * p,
69 Cached: cached * p,
70 Buffers: buffers,
71 Wired: wired * p,
72 Laundry: laundry * p,
73 }
74
75 ret.Available = ret.Inactive + ret.Cached + ret.Free + ret.Laundry
76 ret.Used = ret.Total - ret.Available
77 ret.UsedPercent = float64(ret.Used) / float64(ret.Total) * 100.0
78
79 return ret, nil
80 }
81
82
83 func SwapMemory() (*SwapMemoryStat, error) {
84 return SwapMemoryWithContext(context.Background())
85 }
86
87
88
89 const (
90 XSWDEV_VERSION11 = 1
91 XSWDEV_VERSION = 2
92 )
93
94
95 type xswdev struct {
96 Version uint32
97 Dev uint64
98 Flags int32
99 NBlks int32
100 Used int32
101 }
102
103
104
105 type xswdev11 struct {
106 Version uint32
107 Dev uint32
108 Flags int32
109 NBlks int32
110 Used int32
111 }
112
113 func SwapMemoryWithContext(ctx context.Context) (*SwapMemoryStat, error) {
114
115 i, err := common.SysctlUint("vm.nswapdev")
116 if err != nil {
117 return nil, err
118 }
119
120 if i == 0 {
121 return nil, errors.New("no swap devices found")
122 }
123
124 c := int(i)
125
126 i, err = common.SysctlUint("vm.stats.vm.v_page_size")
127 if err != nil {
128 return nil, err
129 }
130 pageSize := i
131
132 var buf []byte
133 s := &SwapMemoryStat{}
134 for n := 0; n < c; n++ {
135 buf, err = unix.SysctlRaw("vm.swap_info", n)
136 if err != nil {
137 return nil, err
138 }
139
140
141 xsw := (*xswdev)(unsafe.Pointer(&buf[0]))
142 if xsw.Version == XSWDEV_VERSION11 {
143
144 xsw := (*xswdev11)(unsafe.Pointer(&buf[0]))
145 if xsw.Version != XSWDEV_VERSION11 {
146 return nil, errors.New("xswdev version mismatch(11)")
147 }
148 s.Total += uint64(xsw.NBlks)
149 s.Used += uint64(xsw.Used)
150 } else if xsw.Version != XSWDEV_VERSION {
151 return nil, errors.New("xswdev version mismatch")
152 } else {
153 s.Total += uint64(xsw.NBlks)
154 s.Used += uint64(xsw.Used)
155 }
156
157 }
158
159 if s.Total != 0 {
160 s.UsedPercent = float64(s.Used) / float64(s.Total) * 100
161 }
162 s.Total *= pageSize
163 s.Used *= pageSize
164 s.Free = s.Total - s.Used
165
166 return s, nil
167 }
168
View as plain text