From 397417403568764e347aeb0c65979cdbced02970 Mon Sep 17 00:00:00 2001 From: WAKAYAMA shirou Date: Wed, 23 Apr 2014 12:26:21 +0900 Subject: [PATCH] add initial placeholder of process functions. --- process.go | 76 +++++++++++++++++++++ process_freebsd.go | 138 +++++++++++++++++++++++++++++++++++++++ process_freebsd_amd64.go | 96 +++++++++++++++++++++++++++ process_test.go | 16 +++++ 4 files changed, 326 insertions(+) create mode 100644 process.go create mode 100644 process_freebsd.go create mode 100644 process_freebsd_amd64.go create mode 100644 process_test.go diff --git a/process.go b/process.go new file mode 100644 index 0000000..8904008 --- /dev/null +++ b/process.go @@ -0,0 +1,76 @@ +package gopsutil + +type Process struct { + Pid int32 `json:"pid"` + Ppid int32 `json:"ppid"` + Name string `json:"name"` + Exe string `json:"exe"` + Cmdline string `json:"cmdline"` + Create_time int64 + // Parent Process // FIXME: recursive + Status string + Cwd string + Username string + Uids []int32 + Gids []int32 + Terminal string + Nice int32 + Ionice int32 + Rlimit []RlimitStat + Io_counters Io_countersStat + Num_ctx_switches int32 + Num_fds int32 + Num_handles int32 + Num_Threads int32 + // Threads map[string]string + Cpu_times CPU_TimesStat + // Cpu_percent + Cpu_affinity []int32 + Memory_info Memory_infoStat + Memory_info_ex map[string]string + Memory_percent float32 + Memory_maps []Memory_mapsStat + // Children []Process // FIXME: recursive + Open_files []Open_filesStat + Connections []ConnectionStat + Is_running bool +} + +type ConnectionStat struct { + Fd uint32 + Family uint32 + Type uint32 + Laddr string // FIXME + Raddr string // FIXME + Status string +} + +type Open_filesStat struct { + Path string + Fd uint32 +} + +type Memory_infoStat struct { + RSS int32 // bytes + VMS int32 // bytes +} + +type Memory_mapsStat struct { + Path string + RSS int32 + Anonymous int32 + Swap int32 +} + +type RlimitStat struct { + Rresource int32 + Soft int32 + Hard int32 +} + +type Io_countersStat struct { + Read_count int32 + Write_count int32 + Read_bytes int32 + Write_bytes int32 +} diff --git a/process_freebsd.go b/process_freebsd.go new file mode 100644 index 0000000..1b7048d --- /dev/null +++ b/process_freebsd.go @@ -0,0 +1,138 @@ +// +build freebsd + +package gopsutil + +import ( + "bytes" + "encoding/binary" + "syscall" + "unsafe" +) + +// Refresh reloads all the data associated with this process. +func (p *Process) Refresh() error { + + mib := []int32{CTL_KERN, KERN_PROC, KERN_PROC_PID, p.Pid} + + buf, length, err := call_syscall(mib) + if err != nil { + return err + } + proc_k := Kinfo_proc{} + if length != uint64(unsafe.Sizeof(proc_k)) { + return err + } + + k, err := parse_kinfo_proc(buf) + if err != nil { + return err + } + + copy_params(&k, p) + return nil +} + +func copy_params(k *Kinfo_proc, p *Process) error { + p.Exe = byteToString(k.Ki_comm[:]) + p.Ppid = k.Ki_ppid + + return nil +} + +func findProcess(pid int32) (*Process, error) { + mib := []int32{CTL_KERN, KERN_PROC, KERN_PROC_PATHNAME, pid} + + _, _, err := call_syscall(mib) + if err != nil { + return &Process{}, err + } + + return newProcess(pid) +} + +func processes() ([]Process, error) { + results := make([]Process, 0, 50) + + mib := []int32{CTL_KERN, KERN_PROC, KERN_PROC_PROC, 0} + buf, length, err := call_syscall(mib) + if err != nil { + return results, err + } + + // get kinfo_proc size + k := Kinfo_proc{} + procinfo_len := int(unsafe.Sizeof(k)) + count := int(length / uint64(procinfo_len)) + + // parse buf to procs + for i := 0; i < count; i++ { + b := buf[i*procinfo_len : i*procinfo_len+procinfo_len] + k, err := parse_kinfo_proc(b) + if err != nil { + continue + } + p, err := newProcess(int32(k.Ki_pid)) + if err != nil { + continue + } + copy_params(&k, p) + + results = append(results, *p) + } + + return results, nil +} + +func parse_kinfo_proc(buf []byte) (Kinfo_proc, error) { + var k Kinfo_proc + br := bytes.NewReader(buf) + err := binary.Read(br, binary.LittleEndian, &k) + if err != nil { + return k, err + } + + return k, nil +} + +func call_syscall(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 { + b := make([]byte, 0) + return b, length, err + } + if length == 0 { + b := make([]byte, 0) + 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 newProcess(pid int32) (*Process, error) { + p := &Process{Pid: pid} + return p, p.Refresh() +} diff --git a/process_freebsd_amd64.go b/process_freebsd_amd64.go new file mode 100644 index 0000000..e276954 --- /dev/null +++ b/process_freebsd_amd64.go @@ -0,0 +1,96 @@ +// +build freebsd +// +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 Kinfo_proc struct { + Ki_structsize int32 + Ki_layout int32 + Ki_args int64 + Ki_paddr int64 + Ki_addr int64 + Ki_tracep int64 + Ki_textvp int64 + Ki_fd int64 + Ki_vmspace int64 + Ki_wchan int64 + Ki_pid int32 + Ki_ppid int32 + Ki_pgid int32 + Ki_tpgid int32 + Ki_sid int32 + Ki_tsid int32 + Ki_jobc [2]byte + Ki_spare_short1 [2]byte + Ki_tdev int32 + Ki_siglist [16]byte + Ki_sigmask [16]byte + Ki_sigignore [16]byte + Ki_sigcatch [16]byte + Ki_uid int32 + Ki_ruid int32 + Ki_svuid int32 + Ki_rgid int32 + Ki_svgid int32 + Ki_ngroups [2]byte + Ki_spare_short2 [2]byte + Ki_groups [64]byte + Ki_size int64 + Ki_rssize int64 + Ki_swrss int64 + Ki_tsize int64 + Ki_dsize int64 + Ki_ssize int64 + Ki_xstat [2]byte + Ki_acflag [2]byte + Ki_pctcpu int32 + Ki_estcpu int32 + Ki_slptime int32 + Ki_swtime int32 + Ki_cow int32 + Ki_runtime int64 + Ki_start [16]byte + Ki_childtime [16]byte + Ki_flag int64 + Ki_kiflag int64 + Ki_traceflag int32 + Ki_stat [1]byte + Ki_nice [1]byte + Ki_lock [1]byte + Ki_rqindex [1]byte + Ki_oncpu [1]byte + Ki_lastcpu [1]byte + Ki_ocomm [17]byte + Ki_wmesg [9]byte + Ki_login [18]byte + Ki_lockname [9]byte + Ki_comm [20]byte + Ki_emul [17]byte + Ki_sparestrings [68]byte + Ki_spareints [36]byte + Ki_cr_flags int32 + Ki_jid int32 + Ki_numthreads int32 + Ki_tid int32 + Ki_pri int32 + Ki_rusage [144]byte + Ki_rusage_ch [144]byte + Ki_pcb int64 + Ki_kstack int64 + Ki_udata int64 + Ki_tdaddr int64 + Ki_spareptrs [48]byte + Ki_spareint64s [96]byte + Ki_sflag int64 + Ki_tdflags int64 +} diff --git a/process_test.go b/process_test.go new file mode 100644 index 0000000..fb21ec0 --- /dev/null +++ b/process_test.go @@ -0,0 +1,16 @@ +package gopsutil + +import ( + "encoding/json" + "fmt" + "testing" +) + +func Test(t *testing.T) { + v, err := findProcess(0) + if err != nil { + t.Errorf("error %v", err) + } + d, _ := json.Marshal(v) + fmt.Printf("%s\n", d) +}