mirror of https://github.com/shirou/gopsutil
add darwin placeholder. Not working yet.
Currently, test should be failed with NotImplementedError or something.pull/4/head
parent
594816dd1f
commit
a199f2d854
@ -0,0 +1,20 @@
|
||||
// +build darwin
|
||||
|
||||
package gopsutil
|
||||
|
||||
import (
|
||||
"os/exec"
|
||||
"strings"
|
||||
)
|
||||
|
||||
func doSysctrl(mib string) ([]string, error) {
|
||||
out, err := exec.Command("/usr/sbin/sysctl", "-n", mib).Output()
|
||||
if err != nil {
|
||||
return []string{}, err
|
||||
}
|
||||
v := strings.Replace(string(out), "{ ", "", 1)
|
||||
v = strings.Replace(string(v), " }", "", 1)
|
||||
values := strings.Fields(string(v))
|
||||
|
||||
return values, nil
|
||||
}
|
@ -0,0 +1,87 @@
|
||||
// +build darwin
|
||||
|
||||
package gopsutil
|
||||
|
||||
import (
|
||||
"regexp"
|
||||
"strconv"
|
||||
"strings"
|
||||
)
|
||||
|
||||
// sys/resource.h
|
||||
const (
|
||||
CP_USER = 0
|
||||
CP_NICE = 1
|
||||
CP_SYS = 2
|
||||
CP_INTR = 3
|
||||
CP_IDLE = 4
|
||||
CPUSTATES = 5
|
||||
)
|
||||
|
||||
// time.h
|
||||
const (
|
||||
CLOCKS_PER_SEC = 128
|
||||
)
|
||||
|
||||
// TODO: get per cpus
|
||||
func CPUTimes(percpu bool) ([]CPUTimesStat, error) {
|
||||
var ret []CPUTimesStat
|
||||
|
||||
cpuTime, err := doSysctrl("kern.cp_time")
|
||||
if err != nil {
|
||||
return ret, err
|
||||
}
|
||||
|
||||
user, _ := strconv.ParseFloat(cpuTime[CP_USER], 32)
|
||||
nice, _ := strconv.ParseFloat(cpuTime[CP_NICE], 32)
|
||||
sys, _ := strconv.ParseFloat(cpuTime[CP_SYS], 32)
|
||||
idle, _ := strconv.ParseFloat(cpuTime[CP_IDLE], 32)
|
||||
intr, _ := strconv.ParseFloat(cpuTime[CP_INTR], 32)
|
||||
|
||||
c := CPUTimesStat{
|
||||
User: float32(user / CLOCKS_PER_SEC),
|
||||
Nice: float32(nice / CLOCKS_PER_SEC),
|
||||
System: float32(sys / CLOCKS_PER_SEC),
|
||||
Idle: float32(idle / CLOCKS_PER_SEC),
|
||||
Irq: float32(intr / CLOCKS_PER_SEC), // FIXME: correct?
|
||||
}
|
||||
|
||||
ret = append(ret, c)
|
||||
|
||||
return ret, nil
|
||||
}
|
||||
|
||||
// Returns only one CPUInfoStat on FreeBSD
|
||||
func CPUInfo() ([]CPUInfoStat, error) {
|
||||
filename := "/var/run/dmesg.boot"
|
||||
lines, _ := readLines(filename)
|
||||
|
||||
var ret []CPUInfoStat
|
||||
|
||||
c := CPUInfoStat{}
|
||||
for _, line := range lines {
|
||||
if matches := regexp.MustCompile(`CPU:\s+(.+) \(([\d.]+).+\)`).FindStringSubmatch(line); matches != nil {
|
||||
c.ModelName = matches[1]
|
||||
c.Mhz = mustParseFloat64(matches[2])
|
||||
} else if matches := regexp.MustCompile(`Origin = "(.+)" Id = (.+) Family = (.+) Model = (.+) Stepping = (.+)`).FindStringSubmatch(line); matches != nil {
|
||||
c.VendorID = matches[1]
|
||||
c.Family = matches[3]
|
||||
c.Model = matches[4]
|
||||
c.Stepping = mustParseInt32(matches[5])
|
||||
} else if matches := regexp.MustCompile(`Features=.+<(.+)>`).FindStringSubmatch(line); matches != nil {
|
||||
for _, v := range strings.Split(matches[1], ",") {
|
||||
c.Flags = append(c.Flags, strings.ToLower(v))
|
||||
}
|
||||
} else if matches := regexp.MustCompile(`Features2=[a-f\dx]+<(.+)>`).FindStringSubmatch(line); matches != nil {
|
||||
for _, v := range strings.Split(matches[1], ",") {
|
||||
c.Flags = append(c.Flags, strings.ToLower(v))
|
||||
}
|
||||
} else if matches := regexp.MustCompile(`Logical CPUs per core: (\d+)`).FindStringSubmatch(line); matches != nil {
|
||||
// FIXME: no this line?
|
||||
c.Cores = mustParseInt32(matches[1])
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
return append(ret, c), nil
|
||||
}
|
@ -0,0 +1,12 @@
|
||||
// +build darwin
|
||||
|
||||
package gopsutil
|
||||
|
||||
func DiskPartitions(all bool) ([]DiskPartitionStat, error) {
|
||||
|
||||
return nil, NotImplementedError
|
||||
}
|
||||
|
||||
func DiskIOCounters() (map[string]DiskIOCountersStat, error) {
|
||||
return nil, NotImplementedError
|
||||
}
|
@ -0,0 +1,148 @@
|
||||
// +build darwin
|
||||
|
||||
package gopsutil
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"encoding/binary"
|
||||
"io/ioutil"
|
||||
"os"
|
||||
"os/exec"
|
||||
"runtime"
|
||||
"strconv"
|
||||
"strings"
|
||||
"unsafe"
|
||||
)
|
||||
|
||||
const (
|
||||
UTX_USERSIZE = 256 /* include/NetBSD/utmpx.h */
|
||||
UTX_IDSIZE = 4
|
||||
UTX_LINESIZE = 32
|
||||
UTX_HOSTSIZE = 256
|
||||
)
|
||||
|
||||
type utmpx32 struct {
|
||||
UtUser [UTX_USERSIZE]byte /* login name */
|
||||
UtId [UTX_IDSIZE]byte /* id */
|
||||
UtLine [UTX_LINESIZE]byte /* tty name */
|
||||
//TODO UtPid pid_t /* process id creating the entry */
|
||||
UtType [4]byte /* type of this entry */
|
||||
//TODO UtTv timeval32 /* time entry was created */
|
||||
UtHost [UTX_HOSTSIZE]byte /* host name */
|
||||
UtPad [16]byte /* reserved for future use */
|
||||
}
|
||||
|
||||
func HostInfo() (*HostInfoStat, error) {
|
||||
ret := &HostInfoStat{
|
||||
OS: runtime.GOOS,
|
||||
PlatformFamily: "darwin",
|
||||
}
|
||||
|
||||
hostname, err := os.Hostname()
|
||||
if err != nil {
|
||||
return ret, err
|
||||
}
|
||||
ret.Hostname = hostname
|
||||
|
||||
platform, family, version, err := GetPlatformInformation()
|
||||
if err == nil {
|
||||
ret.Platform = platform
|
||||
ret.PlatformFamily = family
|
||||
ret.PlatformVersion = version
|
||||
}
|
||||
system, role, err := GetVirtualization()
|
||||
if err == nil {
|
||||
ret.VirtualizationSystem = system
|
||||
ret.VirtualizationRole = role
|
||||
}
|
||||
|
||||
values, err := doSysctrl("kern.boottime")
|
||||
if err == nil {
|
||||
// ex: { sec = 1392261637, usec = 627534 } Thu Feb 13 12:20:37 2014
|
||||
v := strings.Replace(values[2], ",", "", 1)
|
||||
ret.Uptime = mustParseUint64(v)
|
||||
}
|
||||
|
||||
return ret, nil
|
||||
}
|
||||
|
||||
func BootTime() (int64, error) {
|
||||
values, err := doSysctrl("kern.boottime")
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
// ex: { sec = 1392261637, usec = 627534 } Thu Feb 13 12:20:37 2014
|
||||
v := strings.Replace(values[2], ",", "", 1)
|
||||
|
||||
boottime, err := strconv.ParseInt(v, 10, 64)
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
|
||||
return boottime, nil
|
||||
}
|
||||
|
||||
func Users() ([]UserStat, error) {
|
||||
utmpfile := "/var/run/utmpx"
|
||||
var ret []UserStat
|
||||
|
||||
file, err := os.Open(utmpfile)
|
||||
if err != nil {
|
||||
return ret, err
|
||||
}
|
||||
|
||||
buf, err := ioutil.ReadAll(file)
|
||||
if err != nil {
|
||||
return ret, err
|
||||
}
|
||||
|
||||
u := utmpx32{}
|
||||
entrySize := int(unsafe.Sizeof(u))
|
||||
count := len(buf) / entrySize
|
||||
|
||||
for i := 0; i < count; i++ {
|
||||
b := buf[i*entrySize : i*entrySize+entrySize]
|
||||
|
||||
var u utmpx32
|
||||
br := bytes.NewReader(b)
|
||||
err := binary.Read(br, binary.LittleEndian, &u)
|
||||
if err != nil {
|
||||
continue
|
||||
}
|
||||
user := UserStat{
|
||||
User: byteToString(u.UtUser[:]),
|
||||
// Terminal: byteToString(u.UtLine[:]),
|
||||
Host: byteToString(u.UtHost[:]),
|
||||
// Started: int(u.UtTime),
|
||||
}
|
||||
ret = append(ret, user)
|
||||
}
|
||||
|
||||
return ret, nil
|
||||
|
||||
}
|
||||
|
||||
func GetPlatformInformation() (string, string, string, error) {
|
||||
platform := ""
|
||||
family := ""
|
||||
version := ""
|
||||
|
||||
out, err := exec.Command("uname", "-s").Output()
|
||||
if err == nil {
|
||||
platform = strings.ToLower(strings.TrimSpace(string(out)))
|
||||
}
|
||||
|
||||
out, err = exec.Command("uname", "-r").Output()
|
||||
if err == nil {
|
||||
version = strings.ToLower(strings.TrimSpace(string(out)))
|
||||
}
|
||||
|
||||
return platform, family, version, nil
|
||||
}
|
||||
|
||||
func GetVirtualization() (string, string, error) {
|
||||
system := ""
|
||||
role := ""
|
||||
|
||||
return system, role, nil
|
||||
}
|
@ -0,0 +1,35 @@
|
||||
// +build darwin
|
||||
|
||||
package gopsutil
|
||||
|
||||
import (
|
||||
"strconv"
|
||||
)
|
||||
|
||||
func LoadAvg() (*LoadAvgStat, error) {
|
||||
values, err := doSysctrl("vm.loadavg")
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
load1, err := strconv.ParseFloat(values[0], 64)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
load5, err := strconv.ParseFloat(values[1], 64)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
load15, err := strconv.ParseFloat(values[2], 64)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
ret := &LoadAvgStat{
|
||||
Load1: float64(load1),
|
||||
Load5: float64(load5),
|
||||
Load15: float64(load15),
|
||||
}
|
||||
|
||||
return ret, nil
|
||||
}
|
@ -0,0 +1,74 @@
|
||||
// +build darwin
|
||||
|
||||
package gopsutil
|
||||
|
||||
import (
|
||||
"os/exec"
|
||||
"strings"
|
||||
)
|
||||
|
||||
func getPageSize() (uint64, error) {
|
||||
out, err := exec.Command("pagesize").Output()
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
p := mustParseUint64(string(out))
|
||||
return p, nil
|
||||
}
|
||||
|
||||
// VirtualMemory returns VirtualmemoryStat.
|
||||
func VirtualMemory() (*VirtualMemoryStat, error) {
|
||||
p, _ := getPageSize()
|
||||
|
||||
total, _ := doSysctrl("hw.memsize")
|
||||
free, _ := doSysctrl("vm.page_free_count")
|
||||
/*
|
||||
active, _ := doSysctrl("vm.stats.vm.v_active_count")
|
||||
inactive, _ := doSysctrl("vm.pageout_inactive_used")
|
||||
cache, _ := doSysctrl("vm.stats.vm.v_cache_count")
|
||||
buffer, _ := doSysctrl("vfs.bufspace")
|
||||
wired, _ := doSysctrl("vm.stats.vm.v_wire_count")
|
||||
*/
|
||||
|
||||
ret := &VirtualMemoryStat{
|
||||
Total: mustParseUint64(total[0]) * p,
|
||||
Free: mustParseUint64(free[0]) * p,
|
||||
/*
|
||||
Active: mustParseUint64(active[0]) * p,
|
||||
Inactive: mustParseUint64(inactive[0]) * p,
|
||||
Cached: mustParseUint64(cache[0]) * p,
|
||||
Buffers: mustParseUint64(buffer[0]),
|
||||
Wired: mustParseUint64(wired[0]) * p,
|
||||
*/
|
||||
}
|
||||
|
||||
// TODO: platform independent (worked freebsd?)
|
||||
ret.Available = ret.Free + ret.Buffers + ret.Cached
|
||||
|
||||
ret.Used = ret.Total - ret.Free
|
||||
ret.UsedPercent = float64(ret.Total-ret.Available) / float64(ret.Total) * 100.0
|
||||
|
||||
return ret, nil
|
||||
}
|
||||
|
||||
// SwapMemory returns swapinfo.
|
||||
func SwapMemory() (*SwapMemoryStat, error) {
|
||||
swapUsage, _ := doSysctrl("vm.swapusage")
|
||||
|
||||
var ret *SwapMemoryStat
|
||||
|
||||
total := strings.Replace(swapUsage[3], "M", "", 1)
|
||||
used := strings.Replace(swapUsage[6], "M", "", 1)
|
||||
free := strings.Replace(swapUsage[9], "M", "", 1)
|
||||
|
||||
u := "0"
|
||||
|
||||
ret = &SwapMemoryStat{
|
||||
Total: mustParseUint64(total),
|
||||
Used: mustParseUint64(used),
|
||||
Free: mustParseUint64(free),
|
||||
UsedPercent: mustParseFloat64(u),
|
||||
}
|
||||
|
||||
return ret, nil
|
||||
}
|
@ -0,0 +1,47 @@
|
||||
// +build darwin
|
||||
|
||||
package gopsutil
|
||||
|
||||
import (
|
||||
"os/exec"
|
||||
"strings"
|
||||
)
|
||||
|
||||
func NetIOCounters(pernic bool) ([]NetIOCountersStat, error) {
|
||||
out, err := exec.Command("/usr/sbin/netstat", "-ibdn").Output()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
lines := strings.Split(string(out), "\n")
|
||||
ret := make([]NetIOCountersStat, 0, len(lines)-1)
|
||||
|
||||
for _, line := range lines {
|
||||
values := strings.Fields(line)
|
||||
if len(values) < 1 || values[0] == "Name" {
|
||||
continue
|
||||
}
|
||||
base := 1
|
||||
// sometimes Address is ommitted
|
||||
if len(values) < 13 {
|
||||
base = 0
|
||||
}
|
||||
|
||||
n := NetIOCountersStat{
|
||||
Name: values[0],
|
||||
PacketsRecv: mustParseUint64(values[base+3]),
|
||||
Errin: mustParseUint64(values[base+4]),
|
||||
Dropin: mustParseUint64(values[base+5]),
|
||||
/*
|
||||
BytesRecv: mustParseUint64(values[base+6]),
|
||||
PacketsSent: mustParseUint64(values[base+7]),
|
||||
Errout: mustParseUint64(values[base+8]),
|
||||
BytesSent: mustParseUint64(values[base+9]),
|
||||
Dropout: mustParseUint64(values[base+11]),
|
||||
*/
|
||||
}
|
||||
ret = append(ret, n)
|
||||
}
|
||||
|
||||
return ret, nil
|
||||
}
|
@ -0,0 +1,306 @@
|
||||
// +build darwin
|
||||
|
||||
package gopsutil
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"encoding/binary"
|
||||
"syscall"
|
||||
"unsafe"
|
||||
)
|
||||
|
||||
// MemoryInfoExStat is different between OSes
|
||||
type MemoryInfoExStat struct {
|
||||
}
|
||||
|
||||
type MemoryMapsStat struct {
|
||||
}
|
||||
|
||||
func Pids() ([]int32, error) {
|
||||
var ret []int32
|
||||
procs, err := processes()
|
||||
if err != nil {
|
||||
return ret, nil
|
||||
}
|
||||
|
||||
for _, p := range procs {
|
||||
ret = append(ret, p.Pid)
|
||||
}
|
||||
|
||||
return ret, nil
|
||||
}
|
||||
|
||||
func (p *Process) Ppid() (int32, error) {
|
||||
return 0, NotImplementedError
|
||||
|
||||
k, err := p.getKProc()
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
|
||||
return k.KiPpid, nil
|
||||
}
|
||||
func (p *Process) Name() (string, error) {
|
||||
k, err := p.getKProc()
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
return string(k.KiComm[:]), nil
|
||||
}
|
||||
func (p *Process) Exe() (string, error) {
|
||||
return "", NotImplementedError
|
||||
}
|
||||
func (p *Process) Cmdline() (string, error) {
|
||||
return "", NotImplementedError
|
||||
}
|
||||
func (p *Process) CreateTime() (int64, error) {
|
||||
return 0, NotImplementedError
|
||||
}
|
||||
func (p *Process) Cwd() (string, error) {
|
||||
return "", NotImplementedError
|
||||
}
|
||||
func (p *Process) Parent() (*Process, error) {
|
||||
return p, NotImplementedError
|
||||
}
|
||||
func (p *Process) Status() (string, error) {
|
||||
k, err := p.getKProc()
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
return string(k.KiStat[:]), nil
|
||||
}
|
||||
func (p *Process) Username() (string, error) {
|
||||
return "", NotImplementedError
|
||||
}
|
||||
func (p *Process) Uids() ([]int32, error) {
|
||||
k, err := p.getKProc()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
uids := make([]int32, 0, 3)
|
||||
|
||||
uids = append(uids, int32(k.KiRuid), int32(k.KiUID), int32(k.KiSvuid))
|
||||
|
||||
return uids, nil
|
||||
}
|
||||
func (p *Process) Gids() ([]int32, error) {
|
||||
k, err := p.getKProc()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
gids := make([]int32, 0, 3)
|
||||
gids = append(gids, int32(k.KiRgid), int32(k.KiNgroups[0]), int32(k.KiSvuid))
|
||||
|
||||
return gids, nil
|
||||
}
|
||||
func (p *Process) Terminal() (string, error) {
|
||||
k, err := p.getKProc()
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
ttyNr := uint64(k.KiTdev)
|
||||
|
||||
termmap, err := getTerminalMap()
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
return termmap[ttyNr], nil
|
||||
}
|
||||
func (p *Process) Nice() (int32, error) {
|
||||
return 0, NotImplementedError
|
||||
}
|
||||
func (p *Process) IOnice() (int32, error) {
|
||||
return 0, NotImplementedError
|
||||
}
|
||||
func (p *Process) Rlimit() ([]RlimitStat, error) {
|
||||
var rlimit []RlimitStat
|
||||
return rlimit, NotImplementedError
|
||||
}
|
||||
func (p *Process) IOCounters() (*IOCountersStat, error) {
|
||||
return nil, NotImplementedError
|
||||
}
|
||||
func (p *Process) NumCtxSwitches() (*NumCtxSwitchesStat, error) {
|
||||
return nil, NotImplementedError
|
||||
}
|
||||
func (p *Process) NumFDs() (int32, error) {
|
||||
return 0, NotImplementedError
|
||||
}
|
||||
func (p *Process) NumThreads() (int32, error) {
|
||||
k, err := p.getKProc()
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
|
||||
return k.KiNumthreads, nil
|
||||
}
|
||||
func (p *Process) Threads() (map[string]string, error) {
|
||||
ret := make(map[string]string, 0)
|
||||
return ret, NotImplementedError
|
||||
}
|
||||
func (p *Process) CPUTimes() (*CPUTimesStat, error) {
|
||||
return nil, NotImplementedError
|
||||
}
|
||||
func (p *Process) CPUPercent() (int32, error) {
|
||||
return 0, NotImplementedError
|
||||
}
|
||||
func (p *Process) CPUAffinity() ([]int32, error) {
|
||||
return nil, NotImplementedError
|
||||
}
|
||||
func (p *Process) MemoryInfo() (*MemoryInfoStat, error) {
|
||||
k, err := p.getKProc()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
ret := &MemoryInfoStat{
|
||||
RSS: uint64(k.KiRssize),
|
||||
VMS: uint64(k.KiSize),
|
||||
}
|
||||
|
||||
return ret, nil
|
||||
}
|
||||
func (p *Process) MemoryInfoEx() (*MemoryInfoExStat, error) {
|
||||
return nil, NotImplementedError
|
||||
}
|
||||
func (p *Process) MemoryPercent() (float32, error) {
|
||||
return 0, NotImplementedError
|
||||
}
|
||||
|
||||
func (p *Process) Children() ([]*Process, error) {
|
||||
return nil, NotImplementedError
|
||||
}
|
||||
|
||||
func (p *Process) OpenFiles() ([]OpenFilesStat, error) {
|
||||
return nil, NotImplementedError
|
||||
}
|
||||
|
||||
func (p *Process) Connections() ([]NetConnectionStat, error) {
|
||||
return nil, NotImplementedError
|
||||
}
|
||||
|
||||
func (p *Process) IsRunning() (bool, error) {
|
||||
return true, NotImplementedError
|
||||
}
|
||||
func (p *Process) MemoryMaps(grouped bool) (*[]MemoryMapsStat, error) {
|
||||
var ret []MemoryMapsStat
|
||||
return &ret, NotImplementedError
|
||||
}
|
||||
|
||||
func copyParams(k *KinfoProc, p *Process) error {
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func processes() ([]Process, error) {
|
||||
results := make([]Process, 0, 50)
|
||||
|
||||
mib := []int32{CTL_KERN, KERN_PROC, KERN_PROC_PROC, 0}
|
||||
buf, length, err := callSyscall(mib)
|
||||
if err != nil {
|
||||
return results, err
|
||||
}
|
||||
|
||||
// get kinfo_proc size
|
||||
k := KinfoProc{}
|
||||
procinfoLen := int(unsafe.Sizeof(k))
|
||||
count := int(length / uint64(procinfoLen))
|
||||
|
||||
// parse buf to procs
|
||||
for i := 0; i < count; i++ {
|
||||
b := buf[i*procinfoLen : i*procinfoLen+procinfoLen]
|
||||
k, err := parseKinfoProc(b)
|
||||
if err != nil {
|
||||
continue
|
||||
}
|
||||
p, err := NewProcess(int32(k.KiPid))
|
||||
if err != nil {
|
||||
continue
|
||||
}
|
||||
copyParams(&k, p)
|
||||
|
||||
results = append(results, *p)
|
||||
}
|
||||
|
||||
return results, nil
|
||||
}
|
||||
|
||||
func parseKinfoProc(buf []byte) (KinfoProc, error) {
|
||||
var k KinfoProc
|
||||
br := bytes.NewReader(buf)
|
||||
err := binary.Read(br, binary.LittleEndian, &k)
|
||||
if err != nil {
|
||||
return k, err
|
||||
}
|
||||
|
||||
return k, nil
|
||||
}
|
||||
|
||||
func callSyscall(mib []int32) ([]byte, uint64, error) {
|
||||
miblen := uint64(len(mib))
|
||||
|
||||
// get required buffer size
|
||||
length := uint64(0)
|
||||
_, _, err := syscall.Syscall6(
|
||||
syscall.SYS___SYSCTL,
|
||||
uintptr(unsafe.Pointer(&mib[0])),
|
||||
uintptr(miblen),
|
||||
0,
|
||||
uintptr(unsafe.Pointer(&length)),
|
||||
0,
|
||||
0)
|
||||
if err != 0 {
|
||||
var b []byte
|
||||
return b, length, err
|
||||
}
|
||||
if length == 0 {
|
||||
var b []byte
|
||||
return b, length, err
|
||||
}
|
||||
// get proc info itself
|
||||
buf := make([]byte, length)
|
||||
_, _, err = syscall.Syscall6(
|
||||
syscall.SYS___SYSCTL,
|
||||
uintptr(unsafe.Pointer(&mib[0])),
|
||||
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 (p *Process) getKProc() (*KinfoProc, error) {
|
||||
mib := []int32{CTL_KERN, KERN_PROC, KERN_PROC_PID, p.Pid}
|
||||
|
||||
buf, length, err := callSyscall(mib)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
procK := KinfoProc{}
|
||||
if length != uint64(unsafe.Sizeof(procK)) {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
k, err := parseKinfoProc(buf)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return &k, nil
|
||||
}
|
||||
|
||||
func NewProcess(pid int32) (*Process, error) {
|
||||
p := &Process{Pid: pid}
|
||||
|
||||
return p, nil
|
||||
}
|
@ -0,0 +1,96 @@
|
||||
// +build darwin
|
||||
// +build amd64
|
||||
|
||||
package gopsutil
|
||||
|
||||
// copied from sys/sysctl.h
|
||||
const (
|
||||
CTL_KERN = 1 // "high kernel": proc, limits
|
||||
KERN_PROC = 14 // struct: process entries
|
||||
KERN_PROC_PID = 1 // by process id
|
||||
KERN_PROC_PROC = 8 // only return procs
|
||||
KERN_PROC_PATHNAME = 12 // path to executable
|
||||
)
|
||||
|
||||
// copied from sys/user.h
|
||||
type KinfoProc struct {
|
||||
KiStructsize int32
|
||||
KiLayout int32
|
||||
KiArgs int64
|
||||
KiPaddr int64
|
||||
KiAddr int64
|
||||
KiTracep int64
|
||||
KiTextvp int64
|
||||
KiFd int64
|
||||
KiVmspace int64
|
||||
KiWchan int64
|
||||
KiPid int32
|
||||
KiPpid int32
|
||||
KiPgid int32
|
||||
KiTpgid int32
|
||||
KiSid int32
|
||||
KiTsid int32
|
||||
KiJobc [2]byte
|
||||
KiSpareShort1 [2]byte
|
||||
KiTdev int32
|
||||
KiSiglist [16]byte
|
||||
KiSigmask [16]byte
|
||||
KiSigignore [16]byte
|
||||
KiSigcatch [16]byte
|
||||
KiUID int32
|
||||
KiRuid int32
|
||||
KiSvuid int32
|
||||
KiRgid int32
|
||||
KiSvgid int32
|
||||
KiNgroups [2]byte
|
||||
KiSpareShort2 [2]byte
|
||||
KiGroups [64]byte
|
||||
KiSize int64
|
||||
KiRssize int64
|
||||
KiSwrss int64
|
||||
KiTsize int64
|
||||
KiDsize int64
|
||||
KiSsize int64
|
||||
KiXstat [2]byte
|
||||
KiAcflag [2]byte
|
||||
KiPctcpu int32
|
||||
KiEstcpu int32
|
||||
KiSlptime int32
|
||||
KiSwtime int32
|
||||
KiCow int32
|
||||
KiRuntime int64
|
||||
KiStart [16]byte
|
||||
KiChildtime [16]byte
|
||||
KiFlag int64
|
||||
KiKflag int64
|
||||
KiTraceflag int32
|
||||
KiStat [1]byte
|
||||
KiNice [1]byte
|
||||
KiLock [1]byte
|
||||
KiRqindex [1]byte
|
||||
KiOncpu [1]byte
|
||||
KiLastcpu [1]byte
|
||||
KiOcomm [17]byte
|
||||
KiWmesg [9]byte
|
||||
KiLogin [18]byte
|
||||
KiLockname [9]byte
|
||||
KiComm [20]byte
|
||||
KiEmul [17]byte
|
||||
KiSparestrings [68]byte
|
||||
KiSpareints [36]byte
|
||||
KiCrFlags int32
|
||||
KiJid int32
|
||||
KiNumthreads int32
|
||||
KiTid int32
|
||||
KiPri int32
|
||||
KiRusage [144]byte
|
||||
KiRusageCh [144]byte
|
||||
KiPcb int64
|
||||
KiKstack int64
|
||||
KiUdata int64
|
||||
KiTdaddr int64
|
||||
KiSpareptrs [48]byte
|
||||
KiSpareint64s [96]byte
|
||||
KiSflag int64
|
||||
KiTdflags int64
|
||||
}
|
Loading…
Reference in New Issue