mirror of
https://github.com/MetaCubeX/mihomo.git
synced 2025-12-19 16:30:07 +08:00
96 lines
1.9 KiB
Go
96 lines
1.9 KiB
Go
package memory
|
|
|
|
import (
|
|
"bytes"
|
|
"encoding/binary"
|
|
"errors"
|
|
"unsafe"
|
|
|
|
"golang.org/x/sys/unix"
|
|
)
|
|
|
|
const (
|
|
CTLKern = 1
|
|
KernProc = 14
|
|
KernProcPID = 1
|
|
)
|
|
|
|
func callKernProcSyscall(op int32, arg int32) ([]byte, uint64, error) {
|
|
mib := []int32{CTLKern, KernProc, op, arg, sizeOfKinfoProc, 0}
|
|
mibptr := unsafe.Pointer(&mib[0])
|
|
miblen := uint64(len(mib))
|
|
length := uint64(0)
|
|
_, _, err := unix.Syscall6(
|
|
unix.SYS___SYSCTL,
|
|
uintptr(mibptr),
|
|
uintptr(miblen),
|
|
0,
|
|
uintptr(unsafe.Pointer(&length)),
|
|
0,
|
|
0)
|
|
if err != 0 {
|
|
return nil, length, err
|
|
}
|
|
|
|
count := int32(length / uint64(sizeOfKinfoProc))
|
|
mib = []int32{CTLKern, KernProc, op, arg, sizeOfKinfoProc, count}
|
|
mibptr = unsafe.Pointer(&mib[0])
|
|
miblen = uint64(len(mib))
|
|
// get proc info itself
|
|
buf := make([]byte, length)
|
|
_, _, err = unix.Syscall6(
|
|
unix.SYS___SYSCTL,
|
|
uintptr(mibptr),
|
|
uintptr(miblen),
|
|
uintptr(unsafe.Pointer(&buf[0])),
|
|
uintptr(unsafe.Pointer(&length)),
|
|
0,
|
|
0)
|
|
if err != 0 {
|
|
return buf, length, err
|
|
}
|
|
|
|
return buf, length, nil
|
|
}
|
|
|
|
func parseKinfoProc(buf []byte) (KinfoProc, error) {
|
|
var k KinfoProc
|
|
br := bytes.NewReader(buf)
|
|
err := binary.Read(br, binary.LittleEndian, &k)
|
|
return k, err
|
|
}
|
|
|
|
func getKProc(pid int32) (*KinfoProc, error) {
|
|
buf, length, err := callKernProcSyscall(KernProcPID, pid)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
if length != sizeOfKinfoProc {
|
|
return nil, errors.New("unexpected size of KinfoProc")
|
|
}
|
|
|
|
k, err := parseKinfoProc(buf)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
return &k, nil
|
|
}
|
|
|
|
func GetMemoryInfo(pid int32) (*MemoryInfoStat, error) {
|
|
k, err := getKProc(pid)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
uvmexp, err := unix.SysctlUvmexp("vm.uvmexp")
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
pageSize := uint64(uvmexp.Pagesize)
|
|
|
|
return &MemoryInfoStat{
|
|
RSS: uint64(k.Vm_rssize) * pageSize,
|
|
VMS: uint64(k.Vm_tsize) + uint64(k.Vm_dsize) +
|
|
uint64(k.Vm_ssize),
|
|
}, nil
|
|
}
|