From 02a91378b87edda73af43a660ade7b73386f875b Mon Sep 17 00:00:00 2001 From: Shirou WAKAYAMA Date: Thu, 1 May 2014 18:27:43 +0900 Subject: [PATCH] implements Process.IOCounters on linux. --- README.rst | 2 +- process_linux.go | 33 ++++++++++++++++++++++++++++++++- process_test.go | 31 +++++++++++++++++++++++++------ 3 files changed, 58 insertions(+), 8 deletions(-) diff --git a/README.rst b/README.rst index c14eb62..e1870a3 100644 --- a/README.rst +++ b/README.rst @@ -87,6 +87,7 @@ Current Status - uids (linux, freebsd) - gids (linux, freebsd) - terminal (linux, freebsd) + - io_counters (linux) - nice (linux) - num_fds (linux) - num_threads (linux, freebsd, windows) @@ -111,7 +112,6 @@ Current Status - username - ionice - rlimit - - io_counters - num_ctx_switches - num_handlers - threads diff --git a/process_linux.go b/process_linux.go index fbd7e39..96d65c5 100644 --- a/process_linux.go +++ b/process_linux.go @@ -129,7 +129,7 @@ func (p *Process) Rlimit() ([]RlimitStat, error) { return nil, errors.New("not implemented yet") } func (p *Process) IOCounters() (*IOCountersStat, error) { - return nil, errors.New("not implemented yet") + return p.fillFromIO() } func (p *Process) NumCtxSwitches() (int32, error) { return 0, errors.New("not implemented yet") @@ -335,6 +335,37 @@ func (p *Process) fillFromCmdline() (string, error) { return ret, nil } +// Get IO status from /proc/(pid)/io +func (p *Process) fillFromIO() (*IOCountersStat, error) { + pid := p.Pid + ioPath := filepath.Join("/", "proc", strconv.Itoa(int(pid)), "io") + ioline, err := ioutil.ReadFile(ioPath) + if err != nil { + return nil, err + } + lines := strings.Split(string(ioline), "\n") + ret := &IOCountersStat{} + + for _, line := range lines { + field := strings.Split(line, ":") + if len(field) < 2 { + continue + } + switch field[0] { + case "rchar": + ret.ReadCount = parseInt32(strings.Trim(field[1], " \t")) + case "wchar": + ret.WriteCount = parseInt32(strings.Trim(field[1], " \t")) + case "read_bytes": + ret.ReadBytes = parseInt32(strings.Trim(field[1], " \t")) + case "write_bytes": + ret.WriteBytes = parseInt32(strings.Trim(field[1], " \t")) + } + } + + return ret, nil +} + // Get memory info from /proc/(pid)/statm func (p *Process) fillFromStatm() (*MemoryInfoStat, *MemoryInfoExStat, error) { pid := p.Pid diff --git a/process_test.go b/process_test.go index e8364a3..7612144 100644 --- a/process_test.go +++ b/process_test.go @@ -8,6 +8,15 @@ import ( "testing" ) +func test_getProcess() Process { + checkPid := os.Getpid() + if runtime.GOOS == "windows" { + checkPid = 7960 + } + ret, _ := NewProcess(int32(checkPid)) + return *ret +} + func Test_Pids(t *testing.T) { ret, err := Pids() if err != nil { @@ -68,13 +77,9 @@ func Test_Process_memory_maps(t *testing.T) { } func Test_Process_Ppid(t *testing.T) { - checkPid := os.Getpid() - if runtime.GOOS == "windows" { - checkPid = 7960 - } - ret, err := NewProcess(int32(checkPid)) + p := test_getProcess() - v, err := ret.Ppid() + v, err := p.Ppid() if err != nil { t.Errorf("geting ppid error %v", err) } @@ -83,3 +88,17 @@ func Test_Process_Ppid(t *testing.T) { } } + +func Test_Process_IOCounters(t *testing.T) { + p := test_getProcess() + + v, err := p.IOCounters() + if err != nil { + t.Errorf("geting ppid error %v", err) + } + fmt.Println(v) + if v.ReadCount == 0 { + t.Errorf("return value is 0 %v", v) + } + +}