From 9d38e5c995f3369e0f303f7e82b42123bfe433a3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=8B=A5=E5=B1=B1=E5=8F=B2=E9=83=8E?= Date: Fri, 6 Mar 2015 11:02:59 +0900 Subject: [PATCH] process: add meminfo, cmdline on darwin. --- README.rst | 24 +++++++------- process/process_darwin.go | 82 ++++++++++++++++++++++++++++++++++------------- process/process_test.go | 51 ++++++++++++++++++++++++++++- 3 files changed, 121 insertions(+), 36 deletions(-) diff --git a/README.rst b/README.rst index 9686768..439b69b 100644 --- a/README.rst +++ b/README.rst @@ -150,24 +150,24 @@ Process class ================ ===== ======= ====== ======= name Linux FreeBSD MacOSX Windows -pid x x b x -ppid x x b x -name x x b -cmdline x +pid x x x x +ppid x x x x +name x x x +cmdline x x create_time x -status x x b +status x x x cwd x exe x x x -uids x x b -gids x x b -terminal x x b +uids x x x +gids x x x +terminal x x x io_counters x -nice x +nice x x num_fds x num_ctx_switches x -num_threads x x b +num_threads x x x cpu_times x -memory_info x x b +memory_info x x x memory_info_ex x memory_maps x open_files x @@ -176,7 +176,7 @@ suspend x x x resume x x x terminate x x x kill x x x -username x x b +username x ionice rlimit num_handlres diff --git a/process/process_darwin.go b/process/process_darwin.go index 210e14f..2aa3d41 100644 --- a/process/process_darwin.go +++ b/process/process_darwin.go @@ -4,6 +4,9 @@ package process import ( "bytes" + "os/exec" + "strconv" + "strings" "syscall" "unsafe" @@ -48,12 +51,13 @@ func Pids() ([]int32, error) { } func (p *Process) Ppid() (int32, error) { - k, err := p.getKProc() + r, err := callPs("ppid", p.Pid) + v, err := strconv.Atoi(r[0]) if err != nil { return 0, err } - return k.Proc.P_pid, nil + return int32(v), err } func (p *Process) Name() (string, error) { k, err := p.getKProc() @@ -67,7 +71,8 @@ func (p *Process) Exe() (string, error) { return "", common.NotImplementedError } func (p *Process) Cmdline() (string, error) { - return p.Name() + r, err := callPs("command", p.Pid) + return r[0], err } func (p *Process) CreateTime() (int64, error) { return 0, common.NotImplementedError @@ -79,12 +84,8 @@ func (p *Process) Parent() (*Process, error) { return p, common.NotImplementedError } func (p *Process) Status() (string, error) { - k, err := p.getKProc() - if err != nil { - return "", err - } - - return string(k.Proc.P_stat), nil // TODO + r, err := callPs("state", p.Pid) + return r[0], err } func (p *Process) Uids() ([]int32, error) { k, err := p.getKProc() @@ -110,19 +111,21 @@ func (p *Process) Gids() ([]int32, error) { return gids, nil } func (p *Process) Terminal() (string, error) { - k, err := p.getKProc() - if err != nil { - return "", err - } - - ttyNr := uint64(k.Eproc.Tdev) + return "", common.NotImplementedError + /* + k, err := p.getKProc() + if err != nil { + return "", err + } - termmap, err := getTerminalMap() - if err != nil { - return "", err - } + ttyNr := uint64(k.Eproc.Tdev) + termmap, err := getTerminalMap() + if err != nil { + return "", err + } - return termmap[ttyNr], nil + return termmap[ttyNr], nil + */ } func (p *Process) Nice() (int32, error) { k, err := p.getKProc() @@ -170,14 +173,27 @@ func (p *Process) CPUAffinity() ([]int32, error) { return nil, common.NotImplementedError } func (p *Process) MemoryInfo() (*MemoryInfoStat, error) { - k, err := p.getKProc() + r, err := callPs("rss,vsize,pagein", p.Pid) + if err != nil { + return nil, err + } + rss, err := strconv.Atoi(r[0]) + if err != nil { + return nil, err + } + vms, err := strconv.Atoi(r[1]) + if err != nil { + return nil, err + } + pagein, err := strconv.Atoi(r[2]) if err != nil { return nil, err } ret := &MemoryInfoStat{ - RSS: uint64(k.Eproc.Xrssize), - VMS: uint64(k.Eproc.Xsize), + RSS: uint64(rss), + VMS: uint64(vms), + Swap: uint64(pagein), } return ret, nil @@ -295,3 +311,23 @@ func NewProcess(pid int32) (*Process, error) { return p, nil } + +// call ps command. +// Return value deletes Header line(you must not input wrong arg). +// And splited by Space. Caller have responsibility to manage. +func callPs(arg string, pid int32) ([]string, error) { + out, err := exec.Command("/bin/ps", "-o", arg, "-p", strconv.Itoa(int(pid))).Output() + if err != nil { + return []string{}, err + } + lines := strings.Split(string(out), "\n") + + var ret []string + for _, r := range strings.Split(lines[1], " ") { + if r == "" { + continue + } + ret = append(ret, strings.TrimSpace(r)) + } + return ret, nil +} diff --git a/process/process_test.go b/process/process_test.go index 8375e17..9d70a41 100644 --- a/process/process_test.go +++ b/process/process_test.go @@ -3,6 +3,7 @@ package process import ( "os" "runtime" + "strings" "testing" "time" ) @@ -74,7 +75,31 @@ func Test_Process_memory_maps(t *testing.T) { t.Errorf("memory map get error %v", m) } } +} +func Test_Process_MemoryInfo(t *testing.T) { + p := testGetProcess() + + v, err := p.MemoryInfo() + if err != nil { + t.Errorf("geting ppid error %v", err) + } + empty := MemoryInfoStat{} + if *v == empty { + t.Errorf("could not get memory info %v", v) + } +} +func Test_Process_CmdLine(t *testing.T) { + p := testGetProcess() + + v, err := p.Cmdline() + if err != nil { + t.Errorf("geting ppid error %v", err) + } + + if !strings.HasSuffix(v, "/_test/process.test") { + t.Errorf("invalid cmd line %v", v) + } } func Test_Process_Ppid(t *testing.T) { @@ -89,12 +114,36 @@ func Test_Process_Ppid(t *testing.T) { } } +func Test_Process_Status(t *testing.T) { + p := testGetProcess() + + v, err := p.Status() + if err != nil { + t.Errorf("geting ppid error %v", err) + } + if v != "S+" { + t.Errorf("could not get state %v", v) + } +} + +func Test_Process_Terminal(t *testing.T) { + p := testGetProcess() + + v, err := p.Terminal() + if err != nil { + t.Errorf("geting terminal error %v", err) + } + if v != "S+" { + t.Errorf("could not get state %v", v) + } +} + func Test_Process_IOCounters(t *testing.T) { p := testGetProcess() v, err := p.IOCounters() if err != nil { - t.Errorf("geting ppid error %v", err) + t.Errorf("geting iocounter error %v", err) return } empty := &IOCountersStat{}