Updated gopsutil

This commit is contained in:
Diptanu Choudhury
2016-05-09 08:19:04 -07:00
parent f390261cd0
commit 445b181fec
53 changed files with 2007 additions and 808 deletions

View File

@@ -1,634 +0,0 @@
// Copyright 2009 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
// Package binary implements simple translation between numbers and byte
// sequences and encoding and decoding of varints.
//
// Numbers are translated by reading and writing fixed-size values.
// A fixed-size value is either a fixed-size arithmetic
// type (int8, uint8, int16, float32, complex64, ...)
// or an array or struct containing only fixed-size values.
//
// The varint functions encode and decode single integer values using
// a variable-length encoding; smaller values require fewer bytes.
// For a specification, see
// http://code.google.com/apis/protocolbuffers/docs/encoding.html.
//
// This package favors simplicity over efficiency. Clients that require
// high-performance serialization, especially for large data structures,
// should look at more advanced solutions such as the encoding/gob
// package or protocol buffers.
package process
import (
"errors"
"io"
"math"
"reflect"
)
// A ByteOrder specifies how to convert byte sequences into
// 16-, 32-, or 64-bit unsigned integers.
type ByteOrder interface {
Uint16([]byte) uint16
Uint32([]byte) uint32
Uint64([]byte) uint64
PutUint16([]byte, uint16)
PutUint32([]byte, uint32)
PutUint64([]byte, uint64)
String() string
}
// LittleEndian is the little-endian implementation of ByteOrder.
var LittleEndian littleEndian
// BigEndian is the big-endian implementation of ByteOrder.
var BigEndian bigEndian
type littleEndian struct{}
func (littleEndian) Uint16(b []byte) uint16 { return uint16(b[0]) | uint16(b[1])<<8 }
func (littleEndian) PutUint16(b []byte, v uint16) {
b[0] = byte(v)
b[1] = byte(v >> 8)
}
func (littleEndian) Uint32(b []byte) uint32 {
return uint32(b[0]) | uint32(b[1])<<8 | uint32(b[2])<<16 | uint32(b[3])<<24
}
func (littleEndian) PutUint32(b []byte, v uint32) {
b[0] = byte(v)
b[1] = byte(v >> 8)
b[2] = byte(v >> 16)
b[3] = byte(v >> 24)
}
func (littleEndian) Uint64(b []byte) uint64 {
return uint64(b[0]) | uint64(b[1])<<8 | uint64(b[2])<<16 | uint64(b[3])<<24 |
uint64(b[4])<<32 | uint64(b[5])<<40 | uint64(b[6])<<48 | uint64(b[7])<<56
}
func (littleEndian) PutUint64(b []byte, v uint64) {
b[0] = byte(v)
b[1] = byte(v >> 8)
b[2] = byte(v >> 16)
b[3] = byte(v >> 24)
b[4] = byte(v >> 32)
b[5] = byte(v >> 40)
b[6] = byte(v >> 48)
b[7] = byte(v >> 56)
}
func (littleEndian) String() string { return "LittleEndian" }
func (littleEndian) GoString() string { return "binary.LittleEndian" }
type bigEndian struct{}
func (bigEndian) Uint16(b []byte) uint16 { return uint16(b[1]) | uint16(b[0])<<8 }
func (bigEndian) PutUint16(b []byte, v uint16) {
b[0] = byte(v >> 8)
b[1] = byte(v)
}
func (bigEndian) Uint32(b []byte) uint32 {
return uint32(b[3]) | uint32(b[2])<<8 | uint32(b[1])<<16 | uint32(b[0])<<24
}
func (bigEndian) PutUint32(b []byte, v uint32) {
b[0] = byte(v >> 24)
b[1] = byte(v >> 16)
b[2] = byte(v >> 8)
b[3] = byte(v)
}
func (bigEndian) Uint64(b []byte) uint64 {
return uint64(b[7]) | uint64(b[6])<<8 | uint64(b[5])<<16 | uint64(b[4])<<24 |
uint64(b[3])<<32 | uint64(b[2])<<40 | uint64(b[1])<<48 | uint64(b[0])<<56
}
func (bigEndian) PutUint64(b []byte, v uint64) {
b[0] = byte(v >> 56)
b[1] = byte(v >> 48)
b[2] = byte(v >> 40)
b[3] = byte(v >> 32)
b[4] = byte(v >> 24)
b[5] = byte(v >> 16)
b[6] = byte(v >> 8)
b[7] = byte(v)
}
func (bigEndian) String() string { return "BigEndian" }
func (bigEndian) GoString() string { return "binary.BigEndian" }
// Read reads structured binary data from r into data.
// Data must be a pointer to a fixed-size value or a slice
// of fixed-size values.
// Bytes read from r are decoded using the specified byte order
// and written to successive fields of the data.
// When reading into structs, the field data for fields with
// blank (_) field names is skipped; i.e., blank field names
// may be used for padding.
// When reading into a struct, all non-blank fields must be exported.
func Read(r io.Reader, order ByteOrder, data interface{}) error {
// Fast path for basic types and slices.
if n := intDataSize(data); n != 0 {
var b [8]byte
var bs []byte
if n > len(b) {
bs = make([]byte, n)
} else {
bs = b[:n]
}
if _, err := io.ReadFull(r, bs); err != nil {
return err
}
switch data := data.(type) {
case *int8:
*data = int8(b[0])
case *uint8:
*data = b[0]
case *int16:
*data = int16(order.Uint16(bs))
case *uint16:
*data = order.Uint16(bs)
case *int32:
*data = int32(order.Uint32(bs))
case *uint32:
*data = order.Uint32(bs)
case *int64:
*data = int64(order.Uint64(bs))
case *uint64:
*data = order.Uint64(bs)
case []int8:
for i, x := range bs { // Easier to loop over the input for 8-bit values.
data[i] = int8(x)
}
case []uint8:
copy(data, bs)
case []int16:
for i := range data {
data[i] = int16(order.Uint16(bs[2*i:]))
}
case []uint16:
for i := range data {
data[i] = order.Uint16(bs[2*i:])
}
case []int32:
for i := range data {
data[i] = int32(order.Uint32(bs[4*i:]))
}
case []uint32:
for i := range data {
data[i] = order.Uint32(bs[4*i:])
}
case []int64:
for i := range data {
data[i] = int64(order.Uint64(bs[8*i:]))
}
case []uint64:
for i := range data {
data[i] = order.Uint64(bs[8*i:])
}
}
return nil
}
// Fallback to reflect-based decoding.
v := reflect.ValueOf(data)
size := -1
switch v.Kind() {
case reflect.Ptr:
v = v.Elem()
size = dataSize(v)
case reflect.Slice:
size = dataSize(v)
}
if size < 0 {
return errors.New("binary.Read: invalid type " + reflect.TypeOf(data).String())
}
d := &decoder{order: order, buf: make([]byte, size)}
if _, err := io.ReadFull(r, d.buf); err != nil {
return err
}
d.value(v)
return nil
}
// Write writes the binary representation of data into w.
// Data must be a fixed-size value or a slice of fixed-size
// values, or a pointer to such data.
// Bytes written to w are encoded using the specified byte order
// and read from successive fields of the data.
// When writing structs, zero values are written for fields
// with blank (_) field names.
func Write(w io.Writer, order ByteOrder, data interface{}) error {
// Fast path for basic types and slices.
if n := intDataSize(data); n != 0 {
var b [8]byte
var bs []byte
if n > len(b) {
bs = make([]byte, n)
} else {
bs = b[:n]
}
switch v := data.(type) {
case *int8:
bs = b[:1]
b[0] = byte(*v)
case int8:
bs = b[:1]
b[0] = byte(v)
case []int8:
for i, x := range v {
bs[i] = byte(x)
}
case *uint8:
bs = b[:1]
b[0] = *v
case uint8:
bs = b[:1]
b[0] = byte(v)
case []uint8:
bs = v
case *int16:
bs = b[:2]
order.PutUint16(bs, uint16(*v))
case int16:
bs = b[:2]
order.PutUint16(bs, uint16(v))
case []int16:
for i, x := range v {
order.PutUint16(bs[2*i:], uint16(x))
}
case *uint16:
bs = b[:2]
order.PutUint16(bs, *v)
case uint16:
bs = b[:2]
order.PutUint16(bs, v)
case []uint16:
for i, x := range v {
order.PutUint16(bs[2*i:], x)
}
case *int32:
bs = b[:4]
order.PutUint32(bs, uint32(*v))
case int32:
bs = b[:4]
order.PutUint32(bs, uint32(v))
case []int32:
for i, x := range v {
order.PutUint32(bs[4*i:], uint32(x))
}
case *uint32:
bs = b[:4]
order.PutUint32(bs, *v)
case uint32:
bs = b[:4]
order.PutUint32(bs, v)
case []uint32:
for i, x := range v {
order.PutUint32(bs[4*i:], x)
}
case *int64:
bs = b[:8]
order.PutUint64(bs, uint64(*v))
case int64:
bs = b[:8]
order.PutUint64(bs, uint64(v))
case []int64:
for i, x := range v {
order.PutUint64(bs[8*i:], uint64(x))
}
case *uint64:
bs = b[:8]
order.PutUint64(bs, *v)
case uint64:
bs = b[:8]
order.PutUint64(bs, v)
case []uint64:
for i, x := range v {
order.PutUint64(bs[8*i:], x)
}
}
_, err := w.Write(bs)
return err
}
// Fallback to reflect-based encoding.
v := reflect.Indirect(reflect.ValueOf(data))
size := dataSize(v)
if size < 0 {
return errors.New("binary.Write: invalid type " + reflect.TypeOf(data).String())
}
buf := make([]byte, size)
e := &encoder{order: order, buf: buf}
e.value(v)
_, err := w.Write(buf)
return err
}
// Size returns how many bytes Write would generate to encode the value v, which
// must be a fixed-size value or a slice of fixed-size values, or a pointer to such data.
// If v is neither of these, Size returns -1.
func Size(v interface{}) int {
return dataSize(reflect.Indirect(reflect.ValueOf(v)))
}
// dataSize returns the number of bytes the actual data represented by v occupies in memory.
// For compound structures, it sums the sizes of the elements. Thus, for instance, for a slice
// it returns the length of the slice times the element size and does not count the memory
// occupied by the header. If the type of v is not acceptable, dataSize returns -1.
func dataSize(v reflect.Value) int {
if v.Kind() == reflect.Slice {
if s := sizeof(v.Type().Elem()); s >= 0 {
return s * v.Len()
}
return -1
}
return sizeof(v.Type())
}
// sizeof returns the size >= 0 of variables for the given type or -1 if the type is not acceptable.
func sizeof(t reflect.Type) int {
switch t.Kind() {
case reflect.Array:
if s := sizeof(t.Elem()); s >= 0 {
return s * t.Len()
}
case reflect.Struct:
sum := 0
for i, n := 0, t.NumField(); i < n; i++ {
s := sizeof(t.Field(i).Type)
if s < 0 {
return -1
}
sum += s
}
return sum
case reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64,
reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64,
reflect.Float32, reflect.Float64, reflect.Complex64, reflect.Complex128, reflect.Ptr:
return int(t.Size())
}
return -1
}
type coder struct {
order ByteOrder
buf []byte
}
type decoder coder
type encoder coder
func (d *decoder) uint8() uint8 {
x := d.buf[0]
d.buf = d.buf[1:]
return x
}
func (e *encoder) uint8(x uint8) {
e.buf[0] = x
e.buf = e.buf[1:]
}
func (d *decoder) uint16() uint16 {
x := d.order.Uint16(d.buf[0:2])
d.buf = d.buf[2:]
return x
}
func (e *encoder) uint16(x uint16) {
e.order.PutUint16(e.buf[0:2], x)
e.buf = e.buf[2:]
}
func (d *decoder) uint32() uint32 {
x := d.order.Uint32(d.buf[0:4])
d.buf = d.buf[4:]
return x
}
func (e *encoder) uint32(x uint32) {
e.order.PutUint32(e.buf[0:4], x)
e.buf = e.buf[4:]
}
func (d *decoder) uint64() uint64 {
x := d.order.Uint64(d.buf[0:8])
d.buf = d.buf[8:]
return x
}
func (e *encoder) uint64(x uint64) {
e.order.PutUint64(e.buf[0:8], x)
e.buf = e.buf[8:]
}
func (d *decoder) int8() int8 { return int8(d.uint8()) }
func (e *encoder) int8(x int8) { e.uint8(uint8(x)) }
func (d *decoder) int16() int16 { return int16(d.uint16()) }
func (e *encoder) int16(x int16) { e.uint16(uint16(x)) }
func (d *decoder) int32() int32 { return int32(d.uint32()) }
func (e *encoder) int32(x int32) { e.uint32(uint32(x)) }
func (d *decoder) int64() int64 { return int64(d.uint64()) }
func (e *encoder) int64(x int64) { e.uint64(uint64(x)) }
func (d *decoder) value(v reflect.Value) {
switch v.Kind() {
case reflect.Array:
l := v.Len()
for i := 0; i < l; i++ {
d.value(v.Index(i))
}
case reflect.Struct:
t := v.Type()
l := v.NumField()
for i := 0; i < l; i++ {
// Note: Calling v.CanSet() below is an optimization.
// It would be sufficient to check the field name,
// but creating the StructField info for each field is
// costly (run "go test -bench=ReadStruct" and compare
// results when making changes to this code).
if v := v.Field(i); v.CanSet() || t.Field(i).Name != "_" {
d.value(v)
} else {
d.skip(v)
}
}
case reflect.Slice:
l := v.Len()
for i := 0; i < l; i++ {
d.value(v.Index(i))
}
case reflect.Int8:
v.SetInt(int64(d.int8()))
case reflect.Int16:
v.SetInt(int64(d.int16()))
case reflect.Int32:
v.SetInt(int64(d.int32()))
case reflect.Int64:
v.SetInt(d.int64())
case reflect.Uint8:
v.SetUint(uint64(d.uint8()))
case reflect.Uint16:
v.SetUint(uint64(d.uint16()))
case reflect.Uint32:
v.SetUint(uint64(d.uint32()))
case reflect.Uint64:
v.SetUint(d.uint64())
case reflect.Float32:
v.SetFloat(float64(math.Float32frombits(d.uint32())))
case reflect.Float64:
v.SetFloat(math.Float64frombits(d.uint64()))
case reflect.Complex64:
v.SetComplex(complex(
float64(math.Float32frombits(d.uint32())),
float64(math.Float32frombits(d.uint32())),
))
case reflect.Complex128:
v.SetComplex(complex(
math.Float64frombits(d.uint64()),
math.Float64frombits(d.uint64()),
))
}
}
func (e *encoder) value(v reflect.Value) {
switch v.Kind() {
case reflect.Array:
l := v.Len()
for i := 0; i < l; i++ {
e.value(v.Index(i))
}
case reflect.Struct:
t := v.Type()
l := v.NumField()
for i := 0; i < l; i++ {
// see comment for corresponding code in decoder.value()
if v := v.Field(i); v.CanSet() || t.Field(i).Name != "_" {
e.value(v)
} else {
e.skip(v)
}
}
case reflect.Slice:
l := v.Len()
for i := 0; i < l; i++ {
e.value(v.Index(i))
}
case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
switch v.Type().Kind() {
case reflect.Int8:
e.int8(int8(v.Int()))
case reflect.Int16:
e.int16(int16(v.Int()))
case reflect.Int32:
e.int32(int32(v.Int()))
case reflect.Int64:
e.int64(v.Int())
}
case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr:
switch v.Type().Kind() {
case reflect.Uint8:
e.uint8(uint8(v.Uint()))
case reflect.Uint16:
e.uint16(uint16(v.Uint()))
case reflect.Uint32:
e.uint32(uint32(v.Uint()))
case reflect.Uint64:
e.uint64(v.Uint())
}
case reflect.Float32, reflect.Float64:
switch v.Type().Kind() {
case reflect.Float32:
e.uint32(math.Float32bits(float32(v.Float())))
case reflect.Float64:
e.uint64(math.Float64bits(v.Float()))
}
case reflect.Complex64, reflect.Complex128:
switch v.Type().Kind() {
case reflect.Complex64:
x := v.Complex()
e.uint32(math.Float32bits(float32(real(x))))
e.uint32(math.Float32bits(float32(imag(x))))
case reflect.Complex128:
x := v.Complex()
e.uint64(math.Float64bits(real(x)))
e.uint64(math.Float64bits(imag(x)))
}
}
}
func (d *decoder) skip(v reflect.Value) {
d.buf = d.buf[dataSize(v):]
}
func (e *encoder) skip(v reflect.Value) {
n := dataSize(v)
for i := range e.buf[0:n] {
e.buf[i] = 0
}
e.buf = e.buf[n:]
}
// intDataSize returns the size of the data required to represent the data when encoded.
// It returns zero if the type cannot be implemented by the fast path in Read or Write.
func intDataSize(data interface{}) int {
switch data := data.(type) {
case int8, *int8, *uint8:
return 1
case []int8:
return len(data)
case []uint8:
return len(data)
case int16, *int16, *uint16:
return 2
case []int16:
return 2 * len(data)
case []uint16:
return 2 * len(data)
case int32, *int32, *uint32:
return 4
case []int32:
return 4 * len(data)
case []uint32:
return 4 * len(data)
case int64, *int64, *uint64:
return 8
case []int64:
return 8 * len(data)
case []uint64:
return 8 * len(data)
}
return 0
}

View File

@@ -7,6 +7,7 @@ import (
"github.com/shirou/gopsutil/cpu"
"github.com/shirou/gopsutil/internal/common"
"github.com/shirou/gopsutil/mem"
)
var invoke common.Invoker
@@ -19,13 +20,14 @@ type Process struct {
Pid int32 `json:"pid"`
name string
status string
parent int32
numCtxSwitches *NumCtxSwitchesStat
uids []int32
gids []int32
numThreads int32
memInfo *MemoryInfoStat
lastCPUTimes *cpu.CPUTimesStat
lastCPUTimes *cpu.TimesStat
lastCPUTime time.Time
}
@@ -47,10 +49,10 @@ type RlimitStat struct {
}
type IOCountersStat struct {
ReadCount uint64 `json:"read_count"`
WriteCount uint64 `json:"write_count"`
ReadBytes uint64 `json:"read_bytes"`
WriteBytes uint64 `json:"write_bytes"`
ReadCount uint64 `json:"readCount"`
WriteCount uint64 `json:"writeCount"`
ReadBytes uint64 `json:"readBytes"`
WriteBytes uint64 `json:"writeBytes"`
}
type NumCtxSwitchesStat struct {
@@ -105,45 +107,61 @@ func PidExists(pid int32) (bool, error) {
// If interval is 0, return difference from last call(non-blocking).
// If interval > 0, wait interval sec and return diffrence between start and end.
func (p *Process) CPUPercent(interval time.Duration) (float64, error) {
numcpu := runtime.NumCPU()
calculate := func(t1, t2 *cpu.CPUTimesStat, delta float64) float64 {
if delta == 0 {
return 0
}
delta_proc := (t2.User - t1.User) + (t2.System - t1.System)
overall_percent := ((delta_proc / delta) * 100) * float64(numcpu)
return overall_percent
}
cpuTimes, err := p.CPUTimes()
func (p *Process) Percent(interval time.Duration) (float64, error) {
cpuTimes, err := p.Times()
if err != nil {
return 0, err
}
now := time.Now()
if interval > 0 {
p.lastCPUTimes = cpuTimes
p.lastCPUTime = time.Now()
p.lastCPUTime = now
time.Sleep(interval)
cpuTimes, err = p.CPUTimes()
cpuTimes, err = p.Times()
now = time.Now()
if err != nil {
return 0, err
}
} else {
if p.lastCPUTimes == nil {
// invoked first time
p.lastCPUTimes, err = p.CPUTimes()
if err != nil {
return 0, err
}
p.lastCPUTime = time.Now()
p.lastCPUTimes = cpuTimes
p.lastCPUTime = now
return 0, nil
}
}
delta := (time.Now().Sub(p.lastCPUTime).Seconds()) * float64(numcpu)
ret := calculate(p.lastCPUTimes, cpuTimes, float64(delta))
numcpu := runtime.NumCPU()
delta := (now.Sub(p.lastCPUTime).Seconds()) * float64(numcpu)
ret := calculatePercent(p.lastCPUTimes, cpuTimes, delta, numcpu)
p.lastCPUTimes = cpuTimes
p.lastCPUTime = time.Now()
p.lastCPUTime = now
return ret, nil
}
func calculatePercent(t1, t2 *cpu.TimesStat, delta float64, numcpu int) float64 {
if delta == 0 {
return 0
}
delta_proc := t2.Total() - t1.Total()
overall_percent := ((delta_proc / delta) * 100) * float64(numcpu)
return overall_percent
}
// MemoryPercent returns how many percent of the total RAM this process uses
func (p *Process) MemoryPercent() (float32, error) {
machineMemory, err := mem.VirtualMemory()
if err != nil {
return 0, err
}
total := machineMemory.Total
processMemory, err := p.MemoryInfo()
if err != nil {
return 0, err
}
used := processMemory.RSS
return (100 * float32(used) / float32(total)), nil
}

View File

@@ -4,7 +4,9 @@ package process
import (
"bytes"
"encoding/binary"
"fmt"
"os/exec"
"strconv"
"strings"
"syscall"
@@ -77,8 +79,11 @@ func (p *Process) Name() (string, error) {
return common.IntToString(k.Proc.P_comm[:]), nil
}
func (p *Process) Exe() (string, error) {
return "", common.NotImplementedError
return "", common.ErrNotImplementedError
}
// Cmdline returns the command line arguments of the process as a string with
// each argument separated by 0x20 ascii character.
func (p *Process) Cmdline() (string, error) {
r, err := callPs("command", p.Pid, false)
if err != nil {
@@ -86,11 +91,24 @@ func (p *Process) Cmdline() (string, error) {
}
return strings.Join(r[0], " "), err
}
// CmdlineSlice returns the command line arguments of the process as a slice with each
// element being an argument. Because of current deficiencies in the way that the command
// line arguments are found, single arguments that have spaces in the will actually be
// reported as two separate items. In order to do something better CGO would be needed
// to use the native darwin functions.
func (p *Process) CmdlineSlice() ([]string, error) {
r, err := callPs("command", p.Pid, false)
if err != nil {
return nil, err
}
return r[0], err
}
func (p *Process) CreateTime() (int64, error) {
return 0, common.NotImplementedError
return 0, common.ErrNotImplementedError
}
func (p *Process) Cwd() (string, error) {
return "", common.NotImplementedError
return "", common.ErrNotImplementedError
}
func (p *Process) Parent() (*Process, error) {
rr, err := common.CallLsof(invoke, p.Pid, "-FR")
@@ -124,11 +142,10 @@ func (p *Process) Uids() ([]int32, error) {
return nil, err
}
uids := make([]int32, 0, 3)
// See: http://unix.superglobalmegacorp.com/Net2/newsrc/sys/ucred.h.html
userEffectiveUID := int32(k.Eproc.Ucred.UID)
uids = append(uids, int32(k.Eproc.Pcred.P_ruid), int32(k.Eproc.Ucred.Uid), int32(k.Eproc.Pcred.P_svuid))
return uids, nil
return []int32{userEffectiveUID}, nil
}
func (p *Process) Gids() ([]int32, error) {
k, err := p.getKProc()
@@ -142,7 +159,7 @@ func (p *Process) Gids() ([]int32, error) {
return gids, nil
}
func (p *Process) Terminal() (string, error) {
return "", common.NotImplementedError
return "", common.ErrNotImplementedError
/*
k, err := p.getKProc()
if err != nil {
@@ -166,20 +183,20 @@ func (p *Process) Nice() (int32, error) {
return int32(k.Proc.P_nice), nil
}
func (p *Process) IOnice() (int32, error) {
return 0, common.NotImplementedError
return 0, common.ErrNotImplementedError
}
func (p *Process) Rlimit() ([]RlimitStat, error) {
var rlimit []RlimitStat
return rlimit, common.NotImplementedError
return rlimit, common.ErrNotImplementedError
}
func (p *Process) IOCounters() (*IOCountersStat, error) {
return nil, common.NotImplementedError
return nil, common.ErrNotImplementedError
}
func (p *Process) NumCtxSwitches() (*NumCtxSwitchesStat, error) {
return nil, common.NotImplementedError
return nil, common.ErrNotImplementedError
}
func (p *Process) NumFDs() (int32, error) {
return 0, common.NotImplementedError
return 0, common.ErrNotImplementedError
}
func (p *Process) NumThreads() (int32, error) {
r, err := callPs("utime,stime", p.Pid, true)
@@ -190,10 +207,10 @@ func (p *Process) NumThreads() (int32, error) {
}
func (p *Process) Threads() (map[string]string, error) {
ret := make(map[string]string, 0)
return ret, common.NotImplementedError
return ret, common.ErrNotImplementedError
}
func convertCpuTimes(s string) (ret float64, err error) {
func convertCPUTimes(s string) (ret float64, err error) {
var t int
var _tmp string
if strings.Contains(s, ":") {
@@ -218,23 +235,23 @@ func convertCpuTimes(s string) (ret float64, err error) {
t += h
return float64(t) / ClockTicks, nil
}
func (p *Process) CPUTimes() (*cpu.CPUTimesStat, error) {
func (p *Process) Times() (*cpu.TimesStat, error) {
r, err := callPs("utime,stime", p.Pid, false)
if err != nil {
return nil, err
}
utime, err := convertCpuTimes(r[0][0])
utime, err := convertCPUTimes(r[0][0])
if err != nil {
return nil, err
}
stime, err := convertCpuTimes(r[0][1])
stime, err := convertCPUTimes(r[0][1])
if err != nil {
return nil, err
}
ret := &cpu.CPUTimesStat{
ret := &cpu.TimesStat{
CPU: "cpu",
User: utime,
System: stime,
@@ -242,7 +259,7 @@ func (p *Process) CPUTimes() (*cpu.CPUTimesStat, error) {
return ret, nil
}
func (p *Process) CPUAffinity() ([]int32, error) {
return nil, common.NotImplementedError
return nil, common.ErrNotImplementedError
}
func (p *Process) MemoryInfo() (*MemoryInfoStat, error) {
r, err := callPs("rss,vsize,pagein", p.Pid, false)
@@ -271,10 +288,7 @@ func (p *Process) MemoryInfo() (*MemoryInfoStat, error) {
return ret, nil
}
func (p *Process) MemoryInfoEx() (*MemoryInfoExStat, error) {
return nil, common.NotImplementedError
}
func (p *Process) MemoryPercent() (float32, error) {
return 0, common.NotImplementedError
return nil, common.ErrNotImplementedError
}
func (p *Process) Children() ([]*Process, error) {
@@ -294,24 +308,23 @@ func (p *Process) Children() ([]*Process, error) {
}
func (p *Process) OpenFiles() ([]OpenFilesStat, error) {
return nil, common.NotImplementedError
return nil, common.ErrNotImplementedError
}
func (p *Process) Connections() ([]net.NetConnectionStat, error) {
return net.NetConnectionsPid("all", p.Pid)
func (p *Process) Connections() ([]net.ConnectionStat, error) {
return net.ConnectionsPid("all", p.Pid)
}
func (p *Process) NetIOCounters(pernic bool) ([]net.IOCountersStat, error) {
return nil, common.ErrNotImplementedError
}
func (p *Process) IsRunning() (bool, error) {
return true, common.NotImplementedError
return true, common.ErrNotImplementedError
}
func (p *Process) MemoryMaps(grouped bool) (*[]MemoryMapsStat, error) {
var ret []MemoryMapsStat
return &ret, common.NotImplementedError
}
func copyParams(k *KinfoProc, p *Process) error {
return nil
return &ret, common.ErrNotImplementedError
}
func processes() ([]Process, error) {
@@ -346,8 +359,6 @@ func processes() ([]Process, error) {
if err != nil {
continue
}
copyParams(&k, p)
results = append(results, *p)
}
@@ -358,7 +369,7 @@ func parseKinfoProc(buf []byte) (KinfoProc, error) {
var k KinfoProc
br := bytes.NewReader(buf)
err := Read(br, LittleEndian, &k)
err := common.Read(br, binary.LittleEndian, &k)
if err != nil {
return k, err
}
@@ -366,6 +377,8 @@ func parseKinfoProc(buf []byte) (KinfoProc, error) {
return k, nil
}
// Returns a proc as defined here:
// http://unix.superglobalmegacorp.com/Net2/newsrc/sys/kinfo_proc.h.html
func (p *Process) getKProc() (*KinfoProc, error) {
mib := []int32{CTLKern, KernProc, KernProcPID, p.Pid}
procK := KinfoProc{}
@@ -401,15 +414,20 @@ func NewProcess(pid int32) (*Process, error) {
// And splited by Space. Caller have responsibility to manage.
// If passed arg pid is 0, get information from all process.
func callPs(arg string, pid int32, threadOption bool) ([][]string, error) {
bin, err := exec.LookPath("ps")
if err != nil {
return [][]string{}, err
}
var cmd []string
if pid == 0 { // will get from all processes.
cmd = []string{"-x", "-o", arg}
cmd = []string{"-ax", "-o", arg}
} else if threadOption {
cmd = []string{"-x", "-o", arg, "-M", "-p", strconv.Itoa(int(pid))}
} else {
cmd = []string{"-x", "-o", arg, "-p", strconv.Itoa(int(pid))}
}
out, err := invoke.Command("/bin/ps", cmd...)
out, err := invoke.Command(bin, cmd...)
if err != nil {
return [][]string{}, err
}

View File

@@ -101,7 +101,7 @@ type ucred struct {
type Uucred struct {
Ref int32
Uid uint32
UID uint32
Ngroups int16
Pad_cgo_0 [2]byte
Groups [16]uint32
@@ -197,7 +197,7 @@ type Au_session struct {
}
type Posix_cred struct {
Uid uint32
UID uint32
Ruid uint32
Svuid uint32
Ngroups int16

View File

@@ -5,7 +5,6 @@ package process
import (
"bytes"
"encoding/binary"
"unsafe"
"strings"
"syscall"
@@ -41,7 +40,7 @@ func (p *Process) Ppid() (int32, error) {
return 0, err
}
return k.KiPpid, nil
return k.Ppid, nil
}
func (p *Process) Name() (string, error) {
k, err := p.getKProc()
@@ -49,11 +48,12 @@ func (p *Process) Name() (string, error) {
return "", err
}
return string(k.KiComm[:]), nil
return common.IntToString(k.Comm[:]), nil
}
func (p *Process) Exe() (string, error) {
return "", common.NotImplementedError
return "", common.ErrNotImplementedError
}
func (p *Process) Cmdline() (string, error) {
mib := []int32{CTLKern, KernProc, KernProcArgs, p.Pid}
buf, _, err := common.CallSyscall(mib)
@@ -69,22 +69,60 @@ func (p *Process) Cmdline() (string, error) {
return strings.Join(ret, " "), nil
}
func (p *Process) CmdlineSlice() ([]string, error) {
mib := []int32{CTLKern, KernProc, KernProcArgs, p.Pid}
buf, _, err := common.CallSyscall(mib)
if err != nil {
return nil, err
}
if len(buf) == 0 {
return nil, nil
}
if buf[len(buf)-1] == 0 {
buf = buf[:len(buf)-1]
}
parts := bytes.Split(buf, []byte{0})
var strParts []string
for _, p := range parts {
strParts = append(strParts, string(p))
}
return strParts, nil
}
func (p *Process) CreateTime() (int64, error) {
return 0, common.NotImplementedError
return 0, common.ErrNotImplementedError
}
func (p *Process) Cwd() (string, error) {
return "", common.NotImplementedError
return "", common.ErrNotImplementedError
}
func (p *Process) Parent() (*Process, error) {
return p, common.NotImplementedError
return p, common.ErrNotImplementedError
}
func (p *Process) Status() (string, error) {
k, err := p.getKProc()
if err != nil {
return "", err
}
var s string
switch k.Stat {
case SIDL:
s = "I"
case SRUN:
s = "R"
case SSLEEP:
s = "S"
case SSTOP:
s = "T"
case SZOMB:
s = "Z"
case SWAIT:
s = "W"
case SLOCK:
s = "L"
}
return string(k.KiStat[:]), nil
return s, nil
}
func (p *Process) Uids() ([]int32, error) {
k, err := p.getKProc()
@@ -94,7 +132,7 @@ func (p *Process) Uids() ([]int32, error) {
uids := make([]int32, 0, 3)
uids = append(uids, int32(k.KiRuid), int32(k.KiUID), int32(k.KiSvuid))
uids = append(uids, int32(k.Ruid), int32(k.Uid), int32(k.Svuid))
return uids, nil
}
@@ -105,7 +143,7 @@ func (p *Process) Gids() ([]int32, error) {
}
gids := make([]int32, 0, 3)
gids = append(gids, int32(k.KiRgid), int32(k.KiNgroups[0]), int32(k.KiSvuid))
gids = append(gids, int32(k.Rgid), int32(k.Ngroups), int32(k.Svgid))
return gids, nil
}
@@ -115,7 +153,7 @@ func (p *Process) Terminal() (string, error) {
return "", err
}
ttyNr := uint64(k.KiTdev)
ttyNr := uint64(k.Tdev)
termmap, err := getTerminalMap()
if err != nil {
@@ -125,14 +163,18 @@ func (p *Process) Terminal() (string, error) {
return termmap[ttyNr], nil
}
func (p *Process) Nice() (int32, error) {
return 0, common.NotImplementedError
k, err := p.getKProc()
if err != nil {
return 0, err
}
return int32(k.Nice), nil
}
func (p *Process) IOnice() (int32, error) {
return 0, common.NotImplementedError
return 0, common.ErrNotImplementedError
}
func (p *Process) Rlimit() ([]RlimitStat, error) {
var rlimit []RlimitStat
return rlimit, common.NotImplementedError
return rlimit, common.ErrNotImplementedError
}
func (p *Process) IOCounters() (*IOCountersStat, error) {
k, err := p.getKProc()
@@ -140,15 +182,15 @@ func (p *Process) IOCounters() (*IOCountersStat, error) {
return nil, err
}
return &IOCountersStat{
ReadCount: uint64(k.KiRusage.Inblock),
WriteCount: uint64(k.KiRusage.Oublock),
ReadCount: uint64(k.Rusage.Inblock),
WriteCount: uint64(k.Rusage.Oublock),
}, nil
}
func (p *Process) NumCtxSwitches() (*NumCtxSwitchesStat, error) {
return nil, common.NotImplementedError
return nil, common.ErrNotImplementedError
}
func (p *Process) NumFDs() (int32, error) {
return 0, common.NotImplementedError
return 0, common.ErrNotImplementedError
}
func (p *Process) NumThreads() (int32, error) {
k, err := p.getKProc()
@@ -156,25 +198,25 @@ func (p *Process) NumThreads() (int32, error) {
return 0, err
}
return k.KiNumthreads, nil
return k.Numthreads, nil
}
func (p *Process) Threads() (map[string]string, error) {
ret := make(map[string]string, 0)
return ret, common.NotImplementedError
return ret, common.ErrNotImplementedError
}
func (p *Process) CPUTimes() (*cpu.CPUTimesStat, error) {
func (p *Process) Times() (*cpu.TimesStat, error) {
k, err := p.getKProc()
if err != nil {
return nil, err
}
return &cpu.CPUTimesStat{
return &cpu.TimesStat{
CPU: "cpu",
User: float64(k.KiRusage.Utime.Sec) + float64(k.KiRusage.Utime.Usec)/1000000,
System: float64(k.KiRusage.Stime.Sec) + float64(k.KiRusage.Stime.Usec)/1000000,
User: float64(k.Rusage.Utime.Sec) + float64(k.Rusage.Utime.Usec)/1000000,
System: float64(k.Rusage.Stime.Sec) + float64(k.Rusage.Stime.Usec)/1000000,
}, nil
}
func (p *Process) CPUAffinity() ([]int32, error) {
return nil, common.NotImplementedError
return nil, common.ErrNotImplementedError
}
func (p *Process) MemoryInfo() (*MemoryInfoStat, error) {
k, err := p.getKProc()
@@ -185,18 +227,15 @@ func (p *Process) MemoryInfo() (*MemoryInfoStat, error) {
if err != nil {
return nil, err
}
pageSize := binary.LittleEndian.Uint16([]byte(v))
pageSize := common.LittleEndian.Uint16([]byte(v))
return &MemoryInfoStat{
RSS: uint64(k.KiRssize) * uint64(pageSize),
VMS: uint64(k.KiSize),
RSS: uint64(k.Rssize) * uint64(pageSize),
VMS: uint64(k.Size),
}, nil
}
func (p *Process) MemoryInfoEx() (*MemoryInfoExStat, error) {
return nil, common.NotImplementedError
}
func (p *Process) MemoryPercent() (float32, error) {
return 0, common.NotImplementedError
return nil, common.ErrNotImplementedError
}
func (p *Process) Children() ([]*Process, error) {
@@ -216,24 +255,23 @@ func (p *Process) Children() ([]*Process, error) {
}
func (p *Process) OpenFiles() ([]OpenFilesStat, error) {
return nil, common.NotImplementedError
return nil, common.ErrNotImplementedError
}
func (p *Process) Connections() ([]net.NetConnectionStat, error) {
return nil, common.NotImplementedError
func (p *Process) Connections() ([]net.ConnectionStat, error) {
return nil, common.ErrNotImplementedError
}
func (p *Process) NetIOCounters(pernic bool) ([]net.IOCountersStat, error) {
return nil, common.ErrNotImplementedError
}
func (p *Process) IsRunning() (bool, error) {
return true, common.NotImplementedError
return true, common.ErrNotImplementedError
}
func (p *Process) MemoryMaps(grouped bool) (*[]MemoryMapsStat, error) {
var ret []MemoryMapsStat
return &ret, common.NotImplementedError
}
func copyParams(k *KinfoProc, p *Process) error {
return nil
return &ret, common.ErrNotImplementedError
}
func processes() ([]Process, error) {
@@ -246,22 +284,19 @@ func processes() ([]Process, error) {
}
// get kinfo_proc size
k := KinfoProc{}
procinfoLen := int(unsafe.Sizeof(k))
count := int(length / uint64(procinfoLen))
count := int(length / uint64(sizeOfKinfoProc))
// parse buf to procs
for i := 0; i < count; i++ {
b := buf[i*procinfoLen : i*procinfoLen+procinfoLen]
b := buf[i*sizeOfKinfoProc : (i+1)*sizeOfKinfoProc]
k, err := parseKinfoProc(b)
if err != nil {
continue
}
p, err := NewProcess(int32(k.KiPid))
p, err := NewProcess(int32(k.Pid))
if err != nil {
continue
}
copyParams(&k, p)
results = append(results, *p)
}
@@ -272,7 +307,7 @@ func processes() ([]Process, error) {
func parseKinfoProc(buf []byte) (KinfoProc, error) {
var k KinfoProc
br := bytes.NewReader(buf)
err := binary.Read(br, binary.LittleEndian, &k)
err := common.Read(br, binary.LittleEndian, &k)
return k, err
}
@@ -283,8 +318,7 @@ func (p *Process) getKProc() (*KinfoProc, error) {
if err != nil {
return nil, err
}
procK := KinfoProc{}
if length != uint64(unsafe.Sizeof(procK)) {
if length != sizeOfKinfoProc {
return nil, err
}
@@ -292,7 +326,6 @@ func (p *Process) getKProc() (*KinfoProc, error) {
if err != nil {
return nil, err
}
return &k, nil
}

View File

@@ -1,126 +1,192 @@
// +build freebsd
// +build 386
// Created by cgo -godefs - DO NOT EDIT
// cgo -godefs types_freebsd.go
package process
// copied from sys/sysctl.h
const (
CTLKern = 1 // "high kernel": proc, limits
KernProc = 14 // struct: process entries
KernProcPID = 1 // by process id
KernProcProc = 8 // only return procs
KernProcPathname = 12 // path to executable
KernProcArgs = 7 // get/set arguments/proctitle
CTLKern = 1
KernProc = 14
KernProcPID = 1
KernProcProc = 8
KernProcPathname = 12
KernProcArgs = 7
)
const (
sizeofPtr = 0x4
sizeofShort = 0x2
sizeofInt = 0x4
sizeofLong = 0x4
sizeofLongLong = 0x8
)
const (
sizeOfKinfoVmentry = 0x488
sizeOfKinfoProc = 0x300
)
const (
SIDL = 1
SRUN = 2
SSLEEP = 3
SSTOP = 4
SZOMB = 5
SWAIT = 6
SLOCK = 7
)
type (
_C_short int16
_C_int int32
_C_long int32
_C_long_long int64
)
type Timespec struct {
Sec int32
Nsec int32
Sec int32
Nsec int32
}
type Timeval struct {
Sec int32
Usec int32
Sec int32
Usec int32
}
type Rusage struct {
Utime Timeval
Stime Timeval
Maxrss int32
Ixrss int32
Idrss int32
Isrss int32
Minflt int32
Majflt int32
Nswap int32
Inblock int32
Oublock int32
Msgsnd int32
Msgrcv int32
Nsignals int32
Nvcsw int32
Nivcsw int32
Utime Timeval
Stime Timeval
Maxrss int32
Ixrss int32
Idrss int32
Isrss int32
Minflt int32
Majflt int32
Nswap int32
Inblock int32
Oublock int32
Msgsnd int32
Msgrcv int32
Nsignals int32
Nvcsw int32
Nivcsw int32
}
// copied from sys/user.h
type KinfoProc struct {
KiStructsize int32
KiLayout int32
KiArgs int32
KiPaddr int32
KiAddr int32
KiTracep int32
KiTextvp int32
KiFd int32
KiVmspace int32
KiWchan int32
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 int32
KiRssize int32
KiSwrss int32
KiTsize int32
KiDsize int32
KiSsize int32
KiXstat [2]byte
KiAcflag [2]byte
KiPctcpu int32
KiEstcpu int32
KiSlptime int32
KiSwtime int32
KiCow int32
KiRuntime int64
KiStart [8]byte
KiChildtime [8]byte
KiFlag int32
KiKflag int32
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 Rusage
KiRusageCh [72]byte
KiPcb int32
KiKstack int32
KiUdata int32
KiTdaddr int32
KiSpareptrs [24]byte
KiSpareint64s [48]byte
KiSflag int32
KiTdflags int32
type Rlimit struct {
Cur int64
Max int64
}
type KinfoProc struct {
Structsize int32
Layout int32
Args int32 /* pargs */
Paddr int32 /* proc */
Addr int32 /* user */
Tracep int32 /* vnode */
Textvp int32 /* vnode */
Fd int32 /* filedesc */
Vmspace int32 /* vmspace */
Wchan int32
Pid int32
Ppid int32
Pgid int32
Tpgid int32
Sid int32
Tsid int32
Jobc int16
Spare_short1 int16
Tdev uint32
Siglist [16]byte /* sigset */
Sigmask [16]byte /* sigset */
Sigignore [16]byte /* sigset */
Sigcatch [16]byte /* sigset */
Uid uint32
Ruid uint32
Svuid uint32
Rgid uint32
Svgid uint32
Ngroups int16
Spare_short2 int16
Groups [16]uint32
Size uint32
Rssize int32
Swrss int32
Tsize int32
Dsize int32
Ssize int32
Xstat uint16
Acflag uint16
Pctcpu uint32
Estcpu uint32
Slptime uint32
Swtime uint32
Cow uint32
Runtime uint64
Start Timeval
Childtime Timeval
Flag int32
Kiflag int32
Traceflag int32
Stat int8
Nice int8
Lock int8
Rqindex int8
Oncpu uint8
Lastcpu uint8
Tdname [17]int8
Wmesg [9]int8
Login [18]int8
Lockname [9]int8
Comm [20]int8
Emul [17]int8
Loginclass [18]int8
Sparestrings [50]int8
Spareints [7]int32
Flag2 int32
Fibnum int32
Cr_flags uint32
Jid int32
Numthreads int32
Tid int32
Pri Priority
Rusage Rusage
Rusage_ch Rusage
Pcb int32 /* pcb */
Kstack int32
Udata int32
Tdaddr int32 /* thread */
Spareptrs [6]int32
Sparelongs [12]int32
Sflag int32
Tdflags int32
}
type Priority struct {
Class uint8
Level uint8
Native uint8
User uint8
}
type KinfoVmentry struct {
Structsize int32
Type int32
Start uint64
End uint64
Offset uint64
Vn_fileid uint64
Vn_fsid uint32
Flags int32
Resident int32
Private_resident int32
Protection int32
Ref_count int32
Shadow_count int32
Vn_type int32
Vn_size uint64
Vn_rdev uint32
Vn_mode uint16
Status uint16
X_kve_ispare [12]int32
Path [1024]int8
}

View File

@@ -1,125 +1,192 @@
// +build freebsd
// +build amd64
// Created by cgo -godefs - DO NOT EDIT
// cgo -godefs types_freebsd.go
package process
// copied from sys/sysctl.h
const (
CTLKern = 1 // "high kernel": proc, limits
KernProc = 14 // struct: process entries
KernProcPID = 1 // by process id
KernProcProc = 8 // only return procs
KernProcPathname = 12 // path to executable
KernProcArgs = 7 // get/set arguments/proctitle
CTLKern = 1
KernProc = 14
KernProcPID = 1
KernProcProc = 8
KernProcPathname = 12
KernProcArgs = 7
)
const (
sizeofPtr = 0x8
sizeofShort = 0x2
sizeofInt = 0x4
sizeofLong = 0x8
sizeofLongLong = 0x8
)
const (
sizeOfKinfoVmentry = 0x488
sizeOfKinfoProc = 0x440
)
const (
SIDL = 1
SRUN = 2
SSLEEP = 3
SSTOP = 4
SZOMB = 5
SWAIT = 6
SLOCK = 7
)
type (
_C_short int16
_C_int int32
_C_long int64
_C_long_long int64
)
type Timespec struct {
Sec int64
Nsec int64
Sec int64
Nsec int64
}
type Timeval struct {
Sec int64
Usec int64
Sec int64
Usec int64
}
type Rusage struct {
Utime Timeval
Stime Timeval
Maxrss int64
Ixrss int64
Idrss int64
Isrss int64
Minflt int64
Majflt int64
Nswap int64
Inblock int64
Oublock int64
Msgsnd int64
Msgrcv int64
Nsignals int64
Nvcsw int64
Nivcsw int64
Utime Timeval
Stime Timeval
Maxrss int64
Ixrss int64
Idrss int64
Isrss int64
Minflt int64
Majflt int64
Nswap int64
Inblock int64
Oublock int64
Msgsnd int64
Msgrcv int64
Nsignals int64
Nvcsw int64
Nivcsw int64
}
// 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 Rusage
KiRusageCh [144]byte
KiPcb int64
KiKstack int64
KiUdata int64
KiTdaddr int64
KiSpareptrs [48]byte
KiSpareint64s [96]byte
KiSflag int64
KiTdflags int64
type Rlimit struct {
Cur int64
Max int64
}
type KinfoProc struct {
Structsize int32
Layout int32
Args int64 /* pargs */
Paddr int64 /* proc */
Addr int64 /* user */
Tracep int64 /* vnode */
Textvp int64 /* vnode */
Fd int64 /* filedesc */
Vmspace int64 /* vmspace */
Wchan int64
Pid int32
Ppid int32
Pgid int32
Tpgid int32
Sid int32
Tsid int32
Jobc int16
Spare_short1 int16
Tdev uint32
Siglist [16]byte /* sigset */
Sigmask [16]byte /* sigset */
Sigignore [16]byte /* sigset */
Sigcatch [16]byte /* sigset */
Uid uint32
Ruid uint32
Svuid uint32
Rgid uint32
Svgid uint32
Ngroups int16
Spare_short2 int16
Groups [16]uint32
Size uint64
Rssize int64
Swrss int64
Tsize int64
Dsize int64
Ssize int64
Xstat uint16
Acflag uint16
Pctcpu uint32
Estcpu uint32
Slptime uint32
Swtime uint32
Cow uint32
Runtime uint64
Start Timeval
Childtime Timeval
Flag int64
Kiflag int64
Traceflag int32
Stat int8
Nice int8
Lock int8
Rqindex int8
Oncpu uint8
Lastcpu uint8
Tdname [17]int8
Wmesg [9]int8
Login [18]int8
Lockname [9]int8
Comm [20]int8
Emul [17]int8
Loginclass [18]int8
Sparestrings [50]int8
Spareints [7]int32
Flag2 int32
Fibnum int32
Cr_flags uint32
Jid int32
Numthreads int32
Tid int32
Pri Priority
Rusage Rusage
Rusage_ch Rusage
Pcb int64 /* pcb */
Kstack int64
Udata int64
Tdaddr int64 /* thread */
Spareptrs [6]int64
Sparelongs [12]int64
Sflag int64
Tdflags int64
}
type Priority struct {
Class uint8
Level uint8
Native uint8
User uint8
}
type KinfoVmentry struct {
Structsize int32
Type int32
Start uint64
End uint64
Offset uint64
Vn_fileid uint64
Vn_fsid uint32
Flags int32
Resident int32
Private_resident int32
Protection int32
Ref_count int32
Shadow_count int32
Vn_type int32
Vn_size uint64
Vn_rdev uint32
Vn_mode uint16
Status uint16
X_kve_ispare [12]int32
Path [1024]int8
}

View File

@@ -3,7 +3,9 @@
package process
import (
"bytes"
"encoding/json"
"errors"
"fmt"
"io/ioutil"
"os"
@@ -18,6 +20,8 @@ import (
"github.com/shirou/gopsutil/net"
)
var ErrorNoChildren = errors.New("process does not have children")
const (
PrioProcess = 0 // linux/resource.h
)
@@ -43,30 +47,35 @@ type MemoryMapsStat struct {
Rss uint64 `json:"rss"`
Size uint64 `json:"size"`
Pss uint64 `json:"pss"`
SharedClean uint64 `json:"shared_clean"`
SharedDirty uint64 `json:"shared_dirty"`
PrivateClean uint64 `json:"private_clean"`
PrivateDirty uint64 `json:"private_dirty"`
SharedClean uint64 `json:"sharedClean"`
SharedDirty uint64 `json:"sharedDirty"`
PrivateClean uint64 `json:"privateClean"`
PrivateDirty uint64 `json:"privateDirty"`
Referenced uint64 `json:"referenced"`
Anonymous uint64 `json:"anonymous"`
Swap uint64 `json:"swap"`
}
// String returns JSON value of the process.
func (m MemoryMapsStat) String() string {
s, _ := json.Marshal(m)
return string(s)
}
// Create new Process instance
// This only stores Pid
// NewProcess creates a new Process instance, it only stores the pid and
// checks that the process exists. Other method on Process can be used
// to get more information about the process. An error will be returned
// if the process does not exist.
func NewProcess(pid int32) (*Process, error) {
p := &Process{
Pid: int32(pid),
}
err := p.fillFromStatus()
file, err := os.Open(common.HostProc(strconv.Itoa(int(p.Pid))))
defer file.Close()
return p, err
}
// Ppid returns Parent Process ID of the process.
func (p *Process) Ppid() (int32, error) {
_, ppid, _, _, _, err := p.fillFromStat()
if err != nil {
@@ -74,15 +83,35 @@ func (p *Process) Ppid() (int32, error) {
}
return ppid, nil
}
// Name returns name of the process.
func (p *Process) Name() (string, error) {
if p.name == "" {
if err := p.fillFromStatus(); err != nil {
return "", err
}
}
return p.name, nil
}
// Exe returns executable path of the process.
func (p *Process) Exe() (string, error) {
return p.fillFromExe()
}
// Cmdline returns the command line arguments of the process as a string with
// each argument separated by 0x20 ascii character.
func (p *Process) Cmdline() (string, error) {
return p.fillFromCmdline()
}
// CmdlineSlice returns the command line arguments of the process as a slice with each
// element being an argument.
func (p *Process) CmdlineSlice() ([]string, error) {
return p.fillSliceFromCmdline()
}
// CreateTime returns created time of the process in seconds since the epoch, in UTC.
func (p *Process) CreateTime() (int64, error) {
_, _, _, createTime, _, err := p.fillFromStat()
if err != nil {
@@ -91,23 +120,28 @@ func (p *Process) CreateTime() (int64, error) {
return createTime, nil
}
// Cwd returns current working directory of the process.
func (p *Process) Cwd() (string, error) {
return p.fillFromCwd()
}
// Parent returns parent Process of the process.
func (p *Process) Parent() (*Process, error) {
r, err := callLsof("R", p.Pid)
err := p.fillFromStatus()
if err != nil {
return nil, err
}
if len(r) != 1 { // TODO: pid 1
if p.parent == 0 {
return nil, fmt.Errorf("wrong number of parents")
}
v, err := strconv.Atoi(r[0])
if err != nil {
return nil, err
}
return NewProcess(int32(v))
return NewProcess(p.parent)
}
// Status returns the process status.
// Return value could be one of these.
// R: Running S: Sleep T: Stop I: Idle
// Z: Zombie W: Wait L: Lock
// The charactor is same within all supported platforms.
func (p *Process) Status() (string, error) {
err := p.fillFromStatus()
if err != nil {
@@ -115,6 +149,8 @@ func (p *Process) Status() (string, error) {
}
return p.status, nil
}
// Uids returns user ids of the process as a slice of the int
func (p *Process) Uids() ([]int32, error) {
err := p.fillFromStatus()
if err != nil {
@@ -122,6 +158,8 @@ func (p *Process) Uids() ([]int32, error) {
}
return p.uids, nil
}
// Gids returns group ids of the process as a slice of the int
func (p *Process) Gids() ([]int32, error) {
err := p.fillFromStatus()
if err != nil {
@@ -129,6 +167,8 @@ func (p *Process) Gids() ([]int32, error) {
}
return p.gids, nil
}
// Terminal returns a terminal which is associated with the process.
func (p *Process) Terminal() (string, error) {
terminal, _, _, _, _, err := p.fillFromStat()
if err != nil {
@@ -136,6 +176,9 @@ func (p *Process) Terminal() (string, error) {
}
return terminal, nil
}
// Nice returns a nice value (priority).
// Notice: gopsutil can not set nice value.
func (p *Process) Nice() (int32, error) {
_, _, _, _, nice, err := p.fillFromStat()
if err != nil {
@@ -143,15 +186,23 @@ func (p *Process) Nice() (int32, error) {
}
return nice, nil
}
// IOnice returns process I/O nice value (priority).
func (p *Process) IOnice() (int32, error) {
return 0, common.NotImplementedError
return 0, common.ErrNotImplementedError
}
// Rlimit returns Resource Limits.
func (p *Process) Rlimit() ([]RlimitStat, error) {
return nil, common.NotImplementedError
return nil, common.ErrNotImplementedError
}
// IOCounters returns IO Counters.
func (p *Process) IOCounters() (*IOCountersStat, error) {
return p.fillFromIO()
}
// NumCtxSwitches returns the number of the context switches of the process.
func (p *Process) NumCtxSwitches() (*NumCtxSwitchesStat, error) {
err := p.fillFromStatus()
if err != nil {
@@ -159,10 +210,14 @@ func (p *Process) NumCtxSwitches() (*NumCtxSwitchesStat, error) {
}
return p.numCtxSwitches, nil
}
// NumFDs returns the number of File Descriptors used by the process.
func (p *Process) NumFDs() (int32, error) {
numFds, _, err := p.fillFromfd()
return numFds, err
}
// NumThreads returns the number of threads used by the process.
func (p *Process) NumThreads() (int32, error) {
err := p.fillFromStatus()
if err != nil {
@@ -170,27 +225,41 @@ func (p *Process) NumThreads() (int32, error) {
}
return p.numThreads, nil
}
// Threads returns a map of threads
//
// Notice: Not implemented yet. always returns empty map.
func (p *Process) Threads() (map[string]string, error) {
ret := make(map[string]string, 0)
return ret, nil
}
func (p *Process) CPUTimes() (*cpu.CPUTimesStat, error) {
// Times returns CPU times of the process.
func (p *Process) Times() (*cpu.TimesStat, error) {
_, _, cpuTimes, _, _, err := p.fillFromStat()
if err != nil {
return nil, err
}
return cpuTimes, nil
}
// CPUAffinity returns CPU affinity of the process.
//
// Notice: Not implemented yet.
func (p *Process) CPUAffinity() ([]int32, error) {
return nil, common.NotImplementedError
return nil, common.ErrNotImplementedError
}
// MemoryInfo returns platform in-dependend memory information, such as RSS, VMS and Swap
func (p *Process) MemoryInfo() (*MemoryInfoStat, error) {
_, _, err := p.fillFromStatm()
meminfo, _, err := p.fillFromStatm()
if err != nil {
return nil, err
}
return p.memInfo, nil
return meminfo, nil
}
// MemoryInfoEx returns platform dependend memory information.
func (p *Process) MemoryInfoEx() (*MemoryInfoExStat, error) {
_, memInfoEx, err := p.fillFromStatm()
if err != nil {
@@ -198,13 +267,14 @@ func (p *Process) MemoryInfoEx() (*MemoryInfoExStat, error) {
}
return memInfoEx, nil
}
func (p *Process) MemoryPercent() (float32, error) {
return 0, common.NotImplementedError
}
// Children returns a slice of Process of the process.
func (p *Process) Children() ([]*Process, error) {
pids, err := common.CallPgrep(invoke, p.Pid)
if err != nil {
if pids == nil || len(pids) == 0 {
return nil, ErrorNoChildren
}
return nil, err
}
ret := make([]*Process, 0, len(pids))
@@ -218,12 +288,14 @@ func (p *Process) Children() ([]*Process, error) {
return ret, nil
}
// OpenFiles returns a slice of OpenFilesStat opend by the process.
// OpenFilesStat includes a file path and file descriptor.
func (p *Process) OpenFiles() ([]OpenFilesStat, error) {
_, ofs, err := p.fillFromfd()
if err != nil {
return nil, err
}
ret := make([]OpenFilesStat, 0, len(ofs))
ret := make([]OpenFilesStat, len(ofs))
for i, o := range ofs {
ret[i] = *o
}
@@ -231,12 +303,22 @@ func (p *Process) OpenFiles() ([]OpenFilesStat, error) {
return ret, nil
}
func (p *Process) Connections() ([]net.NetConnectionStat, error) {
return net.NetConnectionsPid("all", p.Pid)
// Connections returns a slice of net.ConnectionStat used by the process.
// This returns all kind of the connection. This measn TCP, UDP or UNIX.
func (p *Process) Connections() ([]net.ConnectionStat, error) {
return net.ConnectionsPid("all", p.Pid)
}
// NetIOCounters returns NetIOCounters of the process.
func (p *Process) NetIOCounters(pernic bool) ([]net.IOCountersStat, error) {
filename := common.HostProc(strconv.Itoa(int(p.Pid)), "net/dev")
return net.IOCountersByFile(pernic, filename)
}
// IsRunning returns whether the process is running or not.
// Not implemented yet.
func (p *Process) IsRunning() (bool, error) {
return true, common.NotImplementedError
return true, common.ErrNotImplementedError
}
// MemoryMaps get memory maps from /proc/(pid)/smaps
@@ -333,7 +415,7 @@ func (p *Process) fillFromfd() (int32, []*OpenFilesStat, error) {
fnames, err := d.Readdirnames(-1)
numFDs := int32(len(fnames))
openfiles := make([]*OpenFilesStat, numFDs)
var openfiles []*OpenFilesStat
for _, fd := range fnames {
fpath := filepath.Join(statPath, fd)
filepath, err := os.Readlink(fpath)
@@ -394,6 +476,28 @@ func (p *Process) fillFromCmdline() (string, error) {
return strings.Join(ret, " "), nil
}
func (p *Process) fillSliceFromCmdline() ([]string, error) {
pid := p.Pid
cmdPath := common.HostProc(strconv.Itoa(int(pid)), "cmdline")
cmdline, err := ioutil.ReadFile(cmdPath)
if err != nil {
return nil, err
}
if len(cmdline) == 0 {
return nil, nil
}
if cmdline[len(cmdline)-1] == 0 {
cmdline = cmdline[:len(cmdline)-1]
}
parts := bytes.Split(cmdline, []byte{0})
var strParts []string
for _, p := range parts {
strParts = append(strParts, string(p))
}
return strParts, nil
}
// Get IO status from /proc/(pid)/io
func (p *Process) fillFromIO() (*IOCountersStat, error) {
pid := p.Pid
@@ -423,9 +527,9 @@ func (p *Process) fillFromIO() (*IOCountersStat, error) {
ret.ReadCount = t
case "syscw":
ret.WriteCount = t
case "read_bytes":
case "readBytes":
ret.ReadBytes = t
case "write_bytes":
case "writeBytes":
ret.WriteBytes = t
}
}
@@ -506,10 +610,13 @@ func (p *Process) fillFromStatus() error {
case "Name":
p.name = strings.Trim(value, " \t")
case "State":
// get between "(" and ")"
s := strings.Index(value, "(") + 1
e := strings.Index(value, ")")
p.status = value[s:e]
p.status = value[0:1]
case "PPid", "Ppid":
pval, err := strconv.ParseInt(value, 10, 32)
if err != nil {
return err
}
p.parent = int32(pval)
case "Uid":
p.uids = make([]int32, 0, 4)
for _, i := range strings.Split(value, "\t") {
@@ -573,7 +680,7 @@ func (p *Process) fillFromStatus() error {
return nil
}
func (p *Process) fillFromStat() (string, int32, *cpu.CPUTimesStat, int64, int32, error) {
func (p *Process) fillFromStat() (string, int32, *cpu.TimesStat, int64, int32, error) {
pid := p.Pid
statPath := common.HostProc(strconv.Itoa(int(pid)), "stat")
contents, err := ioutil.ReadFile(statPath)
@@ -611,7 +718,7 @@ func (p *Process) fillFromStat() (string, int32, *cpu.CPUTimesStat, int64, int32
return "", 0, nil, 0, 0, err
}
cpuTimes := &cpu.CPUTimesStat{
cpuTimes := &cpu.TimesStat{
CPU: "cpu",
User: float64(utime / ClockTicks),
System: float64(stime / ClockTicks),
@@ -633,6 +740,7 @@ func (p *Process) fillFromStat() (string, int32, *cpu.CPUTimesStat, int64, int32
return terminal, int32(ppid), cpuTimes, createTime, nice, nil
}
// Pids returns a slice of process ID list which are running now.
func Pids() ([]int32, error) {
var ret []int32
@@ -657,26 +765,3 @@ func Pids() ([]int32, error) {
return ret, nil
}
func callLsof(arg string, pid int32) ([]string, error) {
var cmd []string
if pid == 0 { // will get from all processes.
cmd = []string{"-F" + arg}
} else {
cmd = []string{"-a", "-F" + arg, "-p", strconv.Itoa(int(pid))}
}
out, err := invoke.Command("/usr/bin/lsof", cmd...)
if err != nil {
return []string{}, err
}
lines := strings.Split(string(out), "\n")
var ret []string
for _, l := range lines[1:] {
if strings.HasPrefix(l, arg) {
ret = append(ret, l[1:]) // delete first char
}
}
return ret, nil
}

View File

@@ -51,6 +51,8 @@ func getTerminalMap() (map[uint64]string, error) {
return ret, nil
}
// SendSignal sends a syscall.Signal to the process.
// Currently, SIGSTOP, SIGCONT, SIGTERM and SIGKILL are supported.
func (p *Process) SendSignal(sig syscall.Signal) error {
sigAsStr := "INT"
switch sig {
@@ -64,9 +66,13 @@ func (p *Process) SendSignal(sig syscall.Signal) error {
sigAsStr = "KILL"
}
cmd := exec.Command("kill", "-s", sigAsStr, strconv.Itoa(int(p.Pid)))
kill, err := exec.LookPath("kill")
if err != nil {
return err
}
cmd := exec.Command(kill, "-s", sigAsStr, strconv.Itoa(int(p.Pid)))
cmd.Stderr = os.Stderr
err := cmd.Run()
err = cmd.Run()
if err != nil {
return err
}
@@ -74,18 +80,27 @@ func (p *Process) SendSignal(sig syscall.Signal) error {
return nil
}
// Suspend sends SIGSTOP to the process.
func (p *Process) Suspend() error {
return p.SendSignal(syscall.SIGSTOP)
}
// Resume sends SIGCONT to the process.
func (p *Process) Resume() error {
return p.SendSignal(syscall.SIGCONT)
}
// Terminate sends SIGTERM to the process.
func (p *Process) Terminate() error {
return p.SendSignal(syscall.SIGTERM)
}
// Kill sends SIGKILL to the process.
func (p *Process) Kill() error {
return p.SendSignal(syscall.SIGKILL)
}
// Username returns a username of the process.
func (p *Process) Username() (string, error) {
uids, err := p.Uids()
if err != nil {

View File

@@ -5,6 +5,7 @@ package process
import (
"errors"
"fmt"
"strings"
"syscall"
"time"
"unsafe"
@@ -12,8 +13,8 @@ import (
"github.com/StackExchange/wmi"
"github.com/shirou/w32"
"github.com/shirou/gopsutil/internal/common"
cpu "github.com/shirou/gopsutil/cpu"
"github.com/shirou/gopsutil/internal/common"
net "github.com/shirou/gopsutil/net"
)
@@ -50,7 +51,7 @@ type Win32_Process struct {
CommandLine *string
Priority uint32
CreationDate *time.Time
ProcessId uint32
ProcessID uint32
ThreadCount uint32
/*
@@ -70,7 +71,7 @@ type Win32_Process struct {
OtherTransferCount uint64
PageFaults uint32
PageFileUsage uint32
ParentProcessId uint32
ParentProcessID uint32
PeakPageFileUsage uint32
PeakVirtualSize uint64
PeakWorkingSetSize uint32
@@ -145,6 +146,17 @@ func (p *Process) Cmdline() (string, error) {
return *dst[0].CommandLine, nil
}
// CmdlineSlice returns the command line arguments of the process as a slice with each
// element being an argument. This merely returns the CommandLine informations passed
// to the process split on the 0x20 ASCII character.
func (p *Process) CmdlineSlice() ([]string, error) {
cmdline, err := p.Cmdline()
if err != nil {
return nil, err
}
return strings.Split(cmdline, " "), nil
}
func (p *Process) CreateTime() (int64, error) {
dst, err := GetWin32Proc(p.Pid)
if err != nil {
@@ -155,28 +167,28 @@ func (p *Process) CreateTime() (int64, error) {
}
func (p *Process) Cwd() (string, error) {
return "", common.NotImplementedError
return "", common.ErrNotImplementedError
}
func (p *Process) Parent() (*Process, error) {
return p, common.NotImplementedError
return p, common.ErrNotImplementedError
}
func (p *Process) Status() (string, error) {
return "", common.NotImplementedError
return "", common.ErrNotImplementedError
}
func (p *Process) Username() (string, error) {
return "", common.NotImplementedError
return "", common.ErrNotImplementedError
}
func (p *Process) Uids() ([]int32, error) {
var uids []int32
return uids, common.NotImplementedError
return uids, common.ErrNotImplementedError
}
func (p *Process) Gids() ([]int32, error) {
var gids []int32
return gids, common.NotImplementedError
return gids, common.ErrNotImplementedError
}
func (p *Process) Terminal() (string, error) {
return "", common.NotImplementedError
return "", common.ErrNotImplementedError
}
// Nice returnes priority in Windows
@@ -188,21 +200,21 @@ func (p *Process) Nice() (int32, error) {
return int32(dst[0].Priority), nil
}
func (p *Process) IOnice() (int32, error) {
return 0, common.NotImplementedError
return 0, common.ErrNotImplementedError
}
func (p *Process) Rlimit() ([]RlimitStat, error) {
var rlimit []RlimitStat
return rlimit, common.NotImplementedError
return rlimit, common.ErrNotImplementedError
}
func (p *Process) IOCounters() (*IOCountersStat, error) {
return nil, common.NotImplementedError
return nil, common.ErrNotImplementedError
}
func (p *Process) NumCtxSwitches() (*NumCtxSwitchesStat, error) {
return nil, common.NotImplementedError
return nil, common.ErrNotImplementedError
}
func (p *Process) NumFDs() (int32, error) {
return 0, common.NotImplementedError
return 0, common.ErrNotImplementedError
}
func (p *Process) NumThreads() (int32, error) {
dst, err := GetWin32Proc(p.Pid)
@@ -213,43 +225,44 @@ func (p *Process) NumThreads() (int32, error) {
}
func (p *Process) Threads() (map[string]string, error) {
ret := make(map[string]string, 0)
return ret, common.NotImplementedError
return ret, common.ErrNotImplementedError
}
func (p *Process) CPUTimes() (*cpu.CPUTimesStat, error) {
return nil, common.NotImplementedError
func (p *Process) Times() (*cpu.TimesStat, error) {
return nil, common.ErrNotImplementedError
}
func (p *Process) CPUAffinity() ([]int32, error) {
return nil, common.NotImplementedError
return nil, common.ErrNotImplementedError
}
func (p *Process) MemoryInfo() (*MemoryInfoStat, error) {
return nil, common.NotImplementedError
return nil, common.ErrNotImplementedError
}
func (p *Process) MemoryInfoEx() (*MemoryInfoExStat, error) {
return nil, common.NotImplementedError
}
func (p *Process) MemoryPercent() (float32, error) {
return 0, common.NotImplementedError
return nil, common.ErrNotImplementedError
}
func (p *Process) Children() ([]*Process, error) {
return nil, common.NotImplementedError
return nil, common.ErrNotImplementedError
}
func (p *Process) OpenFiles() ([]OpenFilesStat, error) {
return nil, common.NotImplementedError
return nil, common.ErrNotImplementedError
}
func (p *Process) Connections() ([]net.NetConnectionStat, error) {
return nil, common.NotImplementedError
func (p *Process) Connections() ([]net.ConnectionStat, error) {
return nil, common.ErrNotImplementedError
}
func (p *Process) NetIOCounters(pernic bool) ([]net.IOCountersStat, error) {
return nil, common.ErrNotImplementedError
}
func (p *Process) IsRunning() (bool, error) {
return true, common.NotImplementedError
return true, common.ErrNotImplementedError
}
func (p *Process) MemoryMaps(grouped bool) (*[]MemoryMapsStat, error) {
ret := make([]MemoryMapsStat, 0)
return &ret, common.NotImplementedError
var ret []MemoryMapsStat
return &ret, common.ErrNotImplementedError
}
func NewProcess(pid int32) (*Process, error) {
@@ -259,20 +272,20 @@ func NewProcess(pid int32) (*Process, error) {
}
func (p *Process) SendSignal(sig syscall.Signal) error {
return common.NotImplementedError
return common.ErrNotImplementedError
}
func (p *Process) Suspend() error {
return common.NotImplementedError
return common.ErrNotImplementedError
}
func (p *Process) Resume() error {
return common.NotImplementedError
return common.ErrNotImplementedError
}
func (p *Process) Terminate() error {
return common.NotImplementedError
return common.ErrNotImplementedError
}
func (p *Process) Kill() error {
return common.NotImplementedError
return common.ErrNotImplementedError
}
func (p *Process) getFromSnapProcess(pid int32) (int32, int32, string, error) {
@@ -315,7 +328,7 @@ func processes() ([]*Process, error) {
}
results := make([]*Process, 0, len(dst))
for _, proc := range dst {
p, err := NewProcess(int32(proc.ProcessId))
p, err := NewProcess(int32(proc.ProcessID))
if err != nil {
continue
}

View File

@@ -0,0 +1,95 @@
// +build ignore
// We still need editing by hands.
// go tool cgo -godefs types_freebsd.go | sed 's/\*int64/int64/' | sed 's/\*byte/int64/' > process_freebsd_amd64.go
/*
Input to cgo -godefs.
*/
// +godefs map struct_pargs int64 /* pargs */
// +godefs map struct_proc int64 /* proc */
// +godefs map struct_user int64 /* user */
// +godefs map struct_vnode int64 /* vnode */
// +godefs map struct_vnode int64 /* vnode */
// +godefs map struct_filedesc int64 /* filedesc */
// +godefs map struct_vmspace int64 /* vmspace */
// +godefs map struct_pcb int64 /* pcb */
// +godefs map struct_thread int64 /* thread */
// +godefs map struct___sigset [16]byte /* sigset */
package process
/*
#include <sys/types.h>
#include <sys/user.h>
enum {
sizeofPtr = sizeof(void*),
};
*/
import "C"
// Machine characteristics; for internal use.
const (
CTLKern = 1 // "high kernel": proc, limits
KernProc = 14 // struct: process entries
KernProcPID = 1 // by process id
KernProcProc = 8 // only return procs
KernProcPathname = 12 // path to executable
KernProcArgs = 7 // get/set arguments/proctitle
)
const (
sizeofPtr = C.sizeofPtr
sizeofShort = C.sizeof_short
sizeofInt = C.sizeof_int
sizeofLong = C.sizeof_long
sizeofLongLong = C.sizeof_longlong
)
const (
sizeOfKinfoVmentry = C.sizeof_struct_kinfo_vmentry
sizeOfKinfoProc = C.sizeof_struct_kinfo_proc
)
// from sys/proc.h
const (
SIDL = 1 /* Process being created by fork. */
SRUN = 2 /* Currently runnable. */
SSLEEP = 3 /* Sleeping on an address. */
SSTOP = 4 /* Process debugging or suspension. */
SZOMB = 5 /* Awaiting collection by parent. */
SWAIT = 6 /* Waiting for interrupt. */
SLOCK = 7 /* Blocked on a lock. */
)
// Basic types
type (
_C_short C.short
_C_int C.int
_C_long C.long
_C_long_long C.longlong
)
// Time
type Timespec C.struct_timespec
type Timeval C.struct_timeval
// Processes
type Rusage C.struct_rusage
type Rlimit C.struct_rlimit
type KinfoProc C.struct_kinfo_proc
type Priority C.struct_priority
type KinfoVmentry C.struct_kinfo_vmentry