1
0
mirror of https://github.com/shirou/gopsutil.git synced 2025-05-04 22:17:34 +08:00

Merge branch 'master' of github.com:shirou/gopsutil

This commit is contained in:
Shirou WAKAYAMA 2014-04-24 15:22:01 +09:00
commit 23b2034406
7 changed files with 202 additions and 96 deletions

View File

@ -66,8 +66,8 @@ Current Status
- disk_usage (linux, freebsd, windows) - disk_usage (linux, freebsd, windows)
- boot_time (linux, freebsd, windows(but little broken)) - boot_time (linux, freebsd, windows(but little broken))
- users (linux, freebsd) - users (linux, freebsd)
- pids (freebsd) - pids (linux, freebsd)
- pid_exists (freebsd) - pid_exists (linux, freebsd)
- not yet - not yet

View File

@ -22,15 +22,10 @@ func HostInfo() (HostInfoStat, error) {
} }
ret.Hostname = hostname ret.Hostname = hostname
uptimemsec, _, err := procGetTickCount.Call()
kernel32, err := syscall.LoadLibrary("kernel32.dll") if uptimemsec == 0 {
if err != nil { return ret, syscall.GetLastError()
return ret, err
} }
defer syscall.FreeLibrary(kernel32)
GetTickCount, _ := syscall.GetProcAddress(kernel32, "GetTickCount")
uptimemsec, _, err := syscall.Syscall(uintptr(GetTickCount), 0, 0, 0, 0)
ret.Uptime = int64(uptimemsec) / 1000 ret.Uptime = int64(uptimemsec) / 1000

View File

@ -6,64 +6,64 @@ type Process struct {
Name string `json:"name"` Name string `json:"name"`
Exe string `json:"exe"` Exe string `json:"exe"`
Cmdline string `json:"cmdline"` Cmdline string `json:"cmdline"`
Create_time int64 Create_time int64 `json:"create_time"`
// Parent Process // FIXME: recursive // Parent Process // FIXME: recursive
Status string Status string `json:"status"`
Cwd string Cwd string `json:"cwd"`
Username string Username string `json:"username"`
Uids []int32 Uids []int32 `json:"uids"`
Gids []int32 Gids []int32 `json:"gids"`
Terminal string Terminal string `json:"terminal"`
Nice int32 Nice int32 `json:"nice"`
Ionice int32 Ionice int32 `json:"ionice"`
Rlimit []RlimitStat Rlimit []RlimitStat `json:"rlimit"`
Io_counters Io_countersStat Io_counters Io_countersStat `json:"io_counter"`
Num_ctx_switches int32 Num_ctx_switches int32 `json:"num_ctx_switches"`
Num_fds int32 Num_fds int32 `json:"num_fds"`
Num_handles int32 Num_handles int32 `json:"num_handles"`
Num_Threads int32 Num_Threads int32 `json:"nunm_threads"`
// Threads map[string]string // Threads map[string]string `json:"threads"`
Cpu_times CPU_TimesStat Cpu_times CPU_TimesStat `json:"cpu_times"`
// Cpu_percent // Cpu_percent `json:"cpu_percent"`
Cpu_affinity []int32 Cpu_affinity []int32 `json:"cpu_affinity"`
Memory_info Memory_infoStat Memory_info Memory_infoStat `json:"memory_info"`
Memory_info_ex map[string]string Memory_info_ex map[string]string `json:"memori_info_ex"`
Memory_percent float32 Memory_percent float32 `json:"memory_percent"`
Memory_maps []Memory_mapsStat Memory_maps []Memory_mapsStat `json:"memory_maps"`
// Children []Process // FIXME: recursive // Children []Process // FIXME: recursive `json:"children"`
Open_files []Open_filesStat Open_files []Open_filesStat `json:"open_files"`
Connections []Net_connectionStat Connections []Net_connectionStat `json:"connections"`
Is_running bool Is_running bool `json:"is_running"`
} }
type Open_filesStat struct { type Open_filesStat struct {
Path string Path string `json:"path"`
Fd uint32 Fd uint32 `json:"fd"`
} }
type Memory_infoStat struct { type Memory_infoStat struct {
RSS int32 // bytes RSS int32 `json:"rss"` // bytes
VMS int32 // bytes VMS int32 `json:"vms"` // bytes
} }
type Memory_mapsStat struct { type Memory_mapsStat struct {
Path string Path string `json:"path"`
RSS int32 RSS int32 `json:"rss"`
Anonymous int32 Anonymous int32 `json:"anonymous"`
Swap int32 Swap int32 `json:"swap"`
} }
type RlimitStat struct { type RlimitStat struct {
Rresource int32 Resource int32 `json:"resource"`
Soft int32 Soft int32 `json:"soft"`
Hard int32 Hard int32 `json:"hard"`
} }
type Io_countersStat struct { type Io_countersStat struct {
Read_count int32 Read_count int32 `json:"read_count"`
Write_count int32 Write_count int32 `json:"write_count"`
Read_bytes int32 Read_bytes int32 `json:"read_bytes"`
Write_bytes int32 Write_bytes int32 `json:"write_bytes"`
} }
func Pid_exists(pid int32) (bool, error) { func Pid_exists(pid int32) (bool, error) {

View File

@ -23,29 +23,6 @@ func Pids() ([]int32, error) {
return ret, nil return ret, nil
} }
// 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 { func copy_params(k *Kinfo_proc, p *Process) error {
p.Exe = byteToString(k.Ki_comm[:]) p.Exe = byteToString(k.Ki_comm[:])
p.Ppid = k.Ki_ppid p.Ppid = k.Ki_ppid
@ -53,17 +30,6 @@ func copy_params(k *Kinfo_proc, p *Process) error {
return nil 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) { func processes() ([]Process, error) {
results := make([]Process, 0, 50) results := make([]Process, 0, 50)
@ -85,7 +51,7 @@ func processes() ([]Process, error) {
if err != nil { if err != nil {
continue continue
} }
p, err := newProcess(int32(k.Ki_pid)) p, err := NewProcess(int32(k.Ki_pid))
if err != nil { if err != nil {
continue continue
} }
@ -146,7 +112,24 @@ func call_syscall(mib []int32) ([]byte, uint64, error) {
return buf, length, nil return buf, length, nil
} }
func newProcess(pid int32) (*Process, error) { func NewProcess(pid int32) (*Process, error) {
p := &Process{Pid: pid} p := &Process{Pid: pid}
return p, p.Refresh() mib := []int32{CTL_KERN, KERN_PROC, KERN_PROC_PID, p.Pid}
buf, length, err := call_syscall(mib)
if err != nil {
return nil, err
}
proc_k := Kinfo_proc{}
if length != uint64(unsafe.Sizeof(proc_k)) {
return nil, err
}
k, err := parse_kinfo_proc(buf)
if err != nil {
return nil, err
}
copy_params(&k, p)
return p, nil
} }

View File

@ -10,11 +10,11 @@ import (
"strings" "strings"
) )
func NewProcess(pid int32) (Process, error) { func NewProcess(pid int32) (*Process, error) {
p := Process{ p := &Process{
Pid: int32(pid), Pid: int32(pid),
} }
go fillFromStat(pid, &p) go fillFromStat(pid, p)
/* /*
// user := parseInt32(fields[13]) // user := parseInt32(fields[13])
@ -101,8 +101,8 @@ func getState(status uint8) (string, error) {
return "running", nil return "running", nil
} }
func processes() ([]Process, error) { func processes() ([]*Process, error) {
ret := make([]Process, 0) ret := make([]*Process, 0)
pids, err := Pids() pids, err := Pids()
if err != nil { if err != nil {

View File

@ -3,6 +3,7 @@ package gopsutil
import ( import (
"encoding/json" "encoding/json"
"fmt" "fmt"
"runtime"
"testing" "testing"
) )
@ -17,7 +18,12 @@ func Test_Pids(t *testing.T) {
} }
func Test_Pid_exists(t *testing.T) { func Test_Pid_exists(t *testing.T) {
ret, err := Pid_exists(1) check_pid := 1
if runtime.GOOS == "windows" {
check_pid = 0
}
ret, err := Pid_exists(int32(check_pid))
if err != nil { if err != nil {
t.Errorf("error %v", err) t.Errorf("error %v", err)
} }
@ -28,7 +34,12 @@ func Test_Pid_exists(t *testing.T) {
} }
func Test_NewProcess(t *testing.T) { func Test_NewProcess(t *testing.T) {
ret, err := NewProcess(1) check_pid := 1
if runtime.GOOS == "windows" {
check_pid = 0
}
ret, err := NewProcess(int32(check_pid))
if err != nil { if err != nil {
t.Errorf("error %v", err) t.Errorf("error %v", err)
} }

117
process_windows.go Normal file
View File

@ -0,0 +1,117 @@
// +build windows
package gopsutil
import (
"fmt"
"syscall"
"unsafe"
)
var (
procCloseHandle = modKernel32.NewProc("CloseHandle")
procCreateToolhelp32Snapshot = modKernel32.NewProc("CreateToolhelp32Snapshot")
procProcess32First = modKernel32.NewProc("Process32FirstW")
procProcess32Next = modKernel32.NewProc("Process32NextW")
)
const (
ERROR_NO_MORE_FILES = 0x12
MAX_PATH = 260
)
type PROCESSENTRY32 struct {
DwSize uint32
CntUsage uint32
Th32ProcessID uint32
Th32DefaultHeapID uintptr
Th32ModuleID uint32
CntThreads uint32
Th32ParentProcessID uint32
PcPriClassBase int32
DwFlags uint32
SzExeFile [MAX_PATH]uint16
}
/*
type SYSTEM_PROCESS_INFORMATION struct {
ULONG NextEntryOffset;
ULONG NumberOfThreads;
BYTE Reserved1[48];
PVOID Reserved2[3];
HANDLE UniqueProcessId;
PVOID Reserved3;
ULONG HandleCount;
BYTE Reserved4[4];
PVOID Reserved5[11];
SIZE_T PeakPagefileUsage;
SIZE_T PrivatePageCount;
LARGE_INTEGER Reserved6[6];
}
*/
func Pids() ([]int32, error) {
ret := make([]int32, 0)
procs, err := processes()
if err != nil {
return ret, nil
}
for _, proc := range procs {
ret = append(ret, proc.Pid)
}
return ret, nil
}
func NewProcess(pid int32) (*Process, error) {
p := &Process{Pid: pid}
if (pid == 0) || (pid == 4) {
p.Cmdline = ""
}
return p, nil
}
func copy_params(pe32 *PROCESSENTRY32, p *Process) error {
p.Ppid = int32(pe32.Th32ParentProcessID)
return nil
}
// Get processes
// This is borrowed from go-ps
func processes() ([]*Process, error) {
handle, _, _ := procCreateToolhelp32Snapshot.Call(
0x00000002,
0)
if handle < 0 {
return nil, syscall.GetLastError()
}
defer procCloseHandle.Call(handle)
var entry PROCESSENTRY32
entry.DwSize = uint32(unsafe.Sizeof(entry))
ret, _, _ := procProcess32First.Call(handle, uintptr(unsafe.Pointer(&entry)))
if ret == 0 {
return nil, fmt.Errorf("Error retrieving process info.")
}
results := make([]*Process, 0)
for {
pid := int32(entry.Th32ProcessID)
p, err := NewProcess(pid)
if err != nil {
break
}
copy_params(&entry, p)
results = append(results, p)
ret, _, _ := procProcess32Next.Call(handle, uintptr(unsafe.Pointer(&entry)))
if ret == 0 {
break
}
}
return results, nil
}