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)
- boot_time (linux, freebsd, windows(but little broken))
- users (linux, freebsd)
- pids (freebsd)
- pid_exists (freebsd)
- pids (linux, freebsd)
- pid_exists (linux, freebsd)
- not yet

View File

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

View File

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

View File

@ -23,29 +23,6 @@ func Pids() ([]int32, error) {
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 {
p.Exe = byteToString(k.Ki_comm[:])
p.Ppid = k.Ki_ppid
@ -53,17 +30,6 @@ func copy_params(k *Kinfo_proc, p *Process) error {
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)
@ -85,7 +51,7 @@ func processes() ([]Process, error) {
if err != nil {
continue
}
p, err := newProcess(int32(k.Ki_pid))
p, err := NewProcess(int32(k.Ki_pid))
if err != nil {
continue
}
@ -146,7 +112,24 @@ func call_syscall(mib []int32) ([]byte, uint64, error) {
return buf, length, nil
}
func newProcess(pid int32) (*Process, error) {
func NewProcess(pid int32) (*Process, error) {
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"
)
func NewProcess(pid int32) (Process, error) {
p := Process{
func NewProcess(pid int32) (*Process, error) {
p := &Process{
Pid: int32(pid),
}
go fillFromStat(pid, &p)
go fillFromStat(pid, p)
/*
// user := parseInt32(fields[13])
@ -101,8 +101,8 @@ func getState(status uint8) (string, error) {
return "running", nil
}
func processes() ([]Process, error) {
ret := make([]Process, 0)
func processes() ([]*Process, error) {
ret := make([]*Process, 0)
pids, err := Pids()
if err != nil {

View File

@ -3,6 +3,7 @@ package gopsutil
import (
"encoding/json"
"fmt"
"runtime"
"testing"
)
@ -17,7 +18,12 @@ func Test_Pids(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 {
t.Errorf("error %v", err)
}
@ -28,7 +34,12 @@ func Test_Pid_exists(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 {
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
}