Permalink
Browse files

Start process interfaces

- ProcList: list of process ids
- ProcState: process state
- ProcMem: process mem info
- ProcTime: process start and cpu times

Change-Id: Ifbfb13b2c6e84ac21aed290ae814aa8dae800b85
  • Loading branch information...
dougm committed Jun 12, 2012
1 parent fb874eb commit 35d6c1bb50ff1913beeecdd6afc0e3b668e86f7d
Showing with 432 additions and 3 deletions.
  1. +37 −0 examples/ps.go
  2. +41 −0 sigar.go
  3. +117 −2 sigar_darwin.go
  4. +24 −1 sigar_format.go
  5. +146 −0 sigar_linux.go
  6. +67 −0 sigar_test.go
View
@@ -0,0 +1,37 @@
+// Copyright (c) 2012 VMware, Inc.
+
+package main
+
+import (
+ "fmt"
+ "github.com/cloudfoundry/gosigar"
+)
+
+func main() {
+ pids := sigar.ProcList{}
+ pids.Get()
+
+ // ps -eo pid,ppid,stime,time,rss,state,comm
+ fmt.Print(" PID PPID STIME TIME RSS S COMMAND\n")
+
+ for _, pid := range pids.List {
+ state := sigar.ProcState{}
+ mem := sigar.ProcMem{}
+ time := sigar.ProcTime{}
+
+ if err := state.Get(pid); err != nil {
+ continue
+ }
+ if err := mem.Get(pid); err != nil {
+ continue
+ }
+ if err := time.Get(pid); err != nil {
+ continue
+ }
+
+ fmt.Printf("%5d %5d %s %s %6d %c %s\n",
+ pid, state.Ppid,
+ time.FormatStartTime(), time.FormatTotal(),
+ mem.Resident/1024, state.State, state.Name)
+ }
+}
View
@@ -45,3 +45,44 @@ type FileSystemUsage struct {
Files uint64
FreeFiles uint64
}
+
+type ProcList struct {
+ List []int
+}
+
+type RunState byte
+
+const (
+ RunStateSleep = 'S'
+ RunStateRun = 'R'
+ RunStateStop = 'T'
+ RunStateZombie = 'Z'
+ RunStateIdle = 'D'
+ RunStateUnknown = '?'
+)
+
+type ProcState struct {
+ Name string
+ State RunState
+ Ppid int
+ Tty int
+ Priority int
+ Nice int
+ Processor int
+}
+
+type ProcMem struct {
+ Size uint64
+ Resident uint64
+ Share uint64
+ MinorFaults uint64
+ MajorFaults uint64
+ PageFaults uint64
+}
+
+type ProcTime struct {
+ StartTime uint64
+ User uint64
+ Sys uint64
+ Total uint64
+}
View
@@ -9,6 +9,7 @@ package sigar
#include <mach/mach_init.h>
#include <mach/mach_host.h>
#include <mach/host_info.h>
+#include <libproc.h>
*/
import "C"
@@ -114,6 +115,108 @@ func (self *FileSystemList) Get() error {
return err
}
+func (self *ProcList) Get() error {
+ n := C.proc_listpids(C.PROC_ALL_PIDS, 0, nil, 0)
+ if n <= 0 {
+ return syscall.EINVAL
+ }
+ buf := make([]byte, n)
+ n = C.proc_listpids(C.PROC_ALL_PIDS, 0, unsafe.Pointer(&buf[0]), n)
+ if n <= 0 {
+ return syscall.ENOMEM
+ }
+
+ var pid int32
+ num := int(n) / binary.Size(pid)
+ list := make([]int, 0, num)
+ bbuf := bytes.NewBuffer(buf)
+
+ for i := 0; i < num; i++ {
+ if err := binary.Read(bbuf, binary.LittleEndian, &pid); err != nil {
+ return err
+ }
+ if pid == 0 {
+ continue
+ }
+
+ list = append(list, int(pid))
+ }
+
+ self.List = list
+
+ return nil
+}
+
+func (self *ProcState) Get(pid int) error {
+ info := C.struct_proc_taskallinfo{}
+
+ if err := task_info(pid, &info); err != nil {
+ return err
+ }
+
+ self.Name = C.GoString(&info.pbsd.pbi_comm[0])
+
+ switch info.pbsd.pbi_status {
+ case C.SIDL:
+ self.State = RunStateIdle
+ case C.SRUN:
+ self.State = RunStateRun
+ case C.SSLEEP:
+ self.State = RunStateSleep
+ case C.SSTOP:
+ self.State = RunStateStop
+ case C.SZOMB:
+ self.State = RunStateZombie
+ default:
+ self.State = RunStateUnknown
+ }
+
+ self.Ppid = int(info.pbsd.pbi_ppid)
+
+ self.Tty = int(info.pbsd.e_tdev)
+
+ self.Priority = int(info.ptinfo.pti_priority)
+
+ self.Nice = int(info.pbsd.pbi_nice)
+
+ return nil
+}
+
+func (self *ProcMem) Get(pid int) error {
+ info := C.struct_proc_taskallinfo{}
+
+ if err := task_info(pid, &info); err != nil {
+ return err
+ }
+
+ self.Size = uint64(info.ptinfo.pti_virtual_size)
+ self.Resident = uint64(info.ptinfo.pti_resident_size)
+ self.PageFaults = uint64(info.ptinfo.pti_faults)
+
+ return nil
+}
+
+func (self *ProcTime) Get(pid int) error {
+ info := C.struct_proc_taskallinfo{}
+
+ if err := task_info(pid, &info); err != nil {
+ return err
+ }
+
+ self.User =
+ uint64(info.ptinfo.pti_total_user) / uint64(time.Millisecond)
+
+ self.Sys =
+ uint64(info.ptinfo.pti_total_system) / uint64(time.Millisecond)
+
+ self.Total = self.User + self.Sys
+
+ self.StartTime = (uint64(info.pbsd.pbi_start_tvsec) * 1000) +
+ (uint64(info.pbsd.pbi_start_tvusec) / 1000)
+
+ return nil
+}
+
func vm_info(vmstat *C.vm_statistics_data_t) error {
var count C.mach_msg_type_number_t = C.HOST_VM_INFO_COUNT
@@ -130,7 +233,7 @@ func vm_info(vmstat *C.vm_statistics_data_t) error {
return nil
}
-//generic Sysctl buffer unmarshalling
+// generic Sysctl buffer unmarshalling
func sysctlbyname(name string, data interface{}) (err error) {
val, err := syscall.Sysctl(name)
if err != nil {
@@ -149,7 +252,7 @@ func sysctlbyname(name string, data interface{}) (err error) {
return binary.Read(bbuf, binary.LittleEndian, data)
}
-//syscall.Getfsstat() wrapper is broken, roll our own to workaround.
+// syscall.Getfsstat() wrapper is broken, roll our own to workaround.
func getfsstat(buf []syscall.Statfs_t, flags int) (n int, err error) {
var ptr uintptr
var size uintptr
@@ -172,3 +275,15 @@ func getfsstat(buf []syscall.Statfs_t, flags int) (n int, err error) {
return
}
+
+func task_info(pid int, info *C.struct_proc_taskallinfo) error {
+ size := C.int(unsafe.Sizeof(*info))
+ ptr := unsafe.Pointer(info)
+
+ n := C.proc_pidinfo(C.int(pid), C.PROC_PIDTASKALLINFO, 0, ptr, size)
+ if n != size {
+ return syscall.ENOMEM
+ }
+
+ return nil
+}
View
@@ -7,9 +7,10 @@ import (
"bytes"
"fmt"
"strconv"
+ "time"
)
-//apr_strfsize
+// Go version of apr_strfsize
func FormatSize(size uint64) string {
ord := []string{"K", "M", "G", "T", "P", "E"}
o := 0
@@ -101,3 +102,25 @@ func (self *Uptime) Format() string {
w.Flush()
return buf.String()
}
+
+func (self *ProcTime) FormatStartTime() string {
+ if self.StartTime == 0 {
+ return "00:00"
+ }
+ start := time.Unix(int64(self.StartTime)/1000, 0)
+ format := "Jan02"
+ if time.Since(start).Seconds() < (60 * 60 * 24) {
+ format = "15:04"
+ }
+ return start.Format(format)
+}
+
+func (self *ProcTime) FormatTotal() string {
+ t := self.Total / 1000
+ ss := t % 60
+ t /= 60
+ mm := t % 60
+ t /= 60
+ hh := t % 24
+ return fmt.Sprintf("%02d:%02d:%02d", hh, mm, ss)
+}
Oops, something went wrong.

0 comments on commit 35d6c1b

Please sign in to comment.