From bcb556f89f33afdf878c697ba4d86b7ad463d91c Mon Sep 17 00:00:00 2001 From: Shirou WAKAYAMA Date: Wed, 23 Apr 2014 17:57:47 +0900 Subject: [PATCH] first commit of process in linux. --- cpu_linux.go | 2 +- net.go | 6 +-- process.go | 14 ----- process_freebsd.go | 14 +++++ process_linux.go | 146 +++++++++++++++++++++++++++++++++++++++++++++++++++++ process_test.go | 11 ++++ 6 files changed, 175 insertions(+), 18 deletions(-) create mode 100644 process_linux.go diff --git a/cpu_linux.go b/cpu_linux.go index 8367527..bd7186f 100644 --- a/cpu_linux.go +++ b/cpu_linux.go @@ -40,7 +40,7 @@ func Cpu_times() ([]CPU_TimesStat, error) { Iowait: iowait, Irq: irq, Softirq: softirq, - Stolen: stolen, + Stolen: stolen, } if len(fields) > 9 { // Linux >= 2.6.11 steal, _ := strconv.ParseUint(fields[9], 10, 64) diff --git a/net.go b/net.go index 5f6ab97..ca7f9ee 100644 --- a/net.go +++ b/net.go @@ -20,8 +20,8 @@ type Net_connectionStat struct { Fd uint32 `json:"fd""` Family uint32 `json:"family""` Type uint32 `json:"type""` - Laddr Addr `json:"laddr""` - Raddr Addr `json:"raddr""` + Laddr Addr `json:"laddr""` + Raddr Addr `json:"raddr""` Status string `json:"status""` - Pid int32 `json:"pid""` + Pid int32 `json:"pid""` } diff --git a/process.go b/process.go index 2cdf7ac..0d880d6 100644 --- a/process.go +++ b/process.go @@ -66,20 +66,6 @@ type Io_countersStat struct { Write_bytes int32 } -func Pids() ([]int32, error) { - ret := make([]int32, 0) - procs, err := processes() - if err != nil { - return ret, nil - } - - for _, p := range procs { - ret = append(ret, p.Pid) - } - - return ret, nil -} - func Pid_exists(pid int32) (bool, error) { pids, err := Pids() if err != nil { diff --git a/process_freebsd.go b/process_freebsd.go index 1b7048d..d210a22 100644 --- a/process_freebsd.go +++ b/process_freebsd.go @@ -9,6 +9,20 @@ import ( "unsafe" ) +func Pids() ([]int32, error) { + ret := make([]int32, 0) + procs, err := processes() + if err != nil { + return ret, nil + } + + for _, p := range procs { + ret = append(ret, p.Pid) + } + + return ret, nil +} + // Refresh reloads all the data associated with this process. func (p *Process) Refresh() error { diff --git a/process_linux.go b/process_linux.go new file mode 100644 index 0000000..b311889 --- /dev/null +++ b/process_linux.go @@ -0,0 +1,146 @@ +// +build linux + +package gopsutil + +import ( + "io/ioutil" + "os" + "path/filepath" + "strconv" + "strings" +) + +func NewProcess(pid int32) (Process, error) { + p := Process{ + Pid: int32(pid), + } + go fillFromStat(pid, &p) + + /* + // user := parseInt32(fields[13]) + //sys := parseInt32(fields[14]) + // convert to millis + self.User = user * (1000 / system.ticks) + self.Sys = sys * (1000 / system.ticks) + self.Total = self.User + self.Sys + + // convert to millis + self.StartTime, _ = strtoull(fields[21]) + self.StartTime /= system.ticks + self.StartTime += system.btime + self.StartTime *= 1000 + */ + return p, nil +} + +func parseInt32(val string) int32 { + vv, _ := strconv.ParseInt(val, 10, 32) + return int32(vv) +} + +/* +func fillFromStatm(pid int32, p *Process) error{ + statPath := filepath.Join("/", "proc", strconv.Itoa(int(pid)), "statm") + contents, err := ioutil.ReadFile(statPath) + if err != nil { + return err + } + fields := strings.Fields(string(contents)) + +} +*/ + +func fillFromStat(pid int32, p *Process) error { + statPath := filepath.Join("/", "proc", strconv.Itoa(int(pid)), "stat") + contents, err := ioutil.ReadFile(statPath) + if err != nil { + return err + } + fields := strings.Fields(string(contents)) + + p.Name = strings.Trim(fields[1], "()") // remove "(" and ")" + p.Status, _ = getState(fields[2][0]) + p.Ppid = parseInt32(fields[3]) + // p.Terminal, _ = strconv.Atoi(fields[6]) + // p.Priority, _ = strconv.Atoi(fields[17]) + p.Nice = parseInt32(fields[18]) + // p.Processor, _ = strconv.Atoi(fields[38]) + return nil +} + +func getState(status uint8) (string, error) { + + /* + >>> psutil.STATUS_RUNNING + 'running' + >>> psutil.STATUS_SLEEPING + 'sleeping' + >>> psutil.STATUS_DISK_SLEEP + 'disk-sleep' + >>> psutil.STATUS_STOPPED + 'stopped' + >>> psutil.STATUS_TRACING_STOP + 'tracing-stop' + >>> psutil.STATUS_ZOMBIE + 'zombie' + >>> psutil.STATUS_DEAD + 'dead' + >>> psutil.STATUS_WAKE_KILL + Traceback (most recent call last): + File "", line 1, in + AttributeError: 'ModuleWrapper' object has no attribute 'STATUS_WAKE_KILL' + >>> psutil.STATUS_WAKING + 'waking' + >>> psutil.STATUS_IDLE + 'idle' + >>> psutil.STATUS_LOCKED + 'locked' + >>> psutil.STATUS_WAITING + 'waiting' + */ + return "running", nil +} + +func processes() ([]Process, error) { + ret := make([]Process, 0) + + pids, err := Pids() + if err != nil { + return ret, err + } + + for _, pid := range pids { + p, err := NewProcess(pid) + if err != nil { + continue // FIXME: should return error? + } + ret = append(ret, p) + } + + return ret, nil +} + +func Pids() ([]int32, error) { + ret := make([]int32, 0) + + d, err := os.Open("/proc") + if err != nil { + return nil, err + } + defer d.Close() + + fnames, err := d.Readdirnames(-1) + if err != nil { + return nil, err + } + for _, fname := range fnames { + pid, err := strconv.ParseInt(fname, 10, 32) + if err != nil { + // if not numeric name, just skip + continue + } + ret = append(ret, int32(pid)) + } + + return ret, nil +} diff --git a/process_test.go b/process_test.go index 5b50e4f..250f500 100644 --- a/process_test.go +++ b/process_test.go @@ -1,6 +1,8 @@ package gopsutil import ( + "encoding/json" + "fmt" "testing" ) @@ -23,5 +25,14 @@ func Test_Pid_exists(t *testing.T) { if ret == false { t.Errorf("could not get init process %v", ret) } +} + +func Test_NewProcess(t *testing.T) { + ret, err := NewProcess(1) + if err != nil { + t.Errorf("error %v", err) + } + d, _ := json.Marshal(ret) + fmt.Println(string(d)) }