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:
commit
23b2034406
@ -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
|
||||
|
||||
|
@ -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
|
||||
|
||||
|
84
process.go
84
process.go
@ -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) {
|
||||
|
@ -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
|
||||
}
|
||||
|
@ -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 {
|
||||
|
@ -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
117
process_windows.go
Normal 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
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user