Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
Canread
Gopsutil
提交
47f6760c
G
Gopsutil
项目概览
Canread
/
Gopsutil
通知
1
Star
0
Fork
0
代码
文件
提交
分支
Tags
贡献者
分支图
Diff
Issue
0
列表
看板
标记
里程碑
合并请求
0
DevOps
流水线
流水线任务
计划
Wiki
0
Wiki
分析
仓库
DevOps
项目成员
Pages
G
Gopsutil
项目概览
项目概览
详情
发布
仓库
仓库
文件
提交
分支
标签
贡献者
分支图
比较
Issue
0
Issue
0
列表
看板
标记
里程碑
合并请求
0
合并请求
0
Pages
DevOps
DevOps
流水线
流水线任务
计划
分析
分析
仓库分析
DevOps
Wiki
0
Wiki
成员
成员
收起侧边栏
关闭侧边栏
动态
分支图
创建新Issue
流水线任务
提交
Issue看板
体验新版 GitCode,发现更多精彩内容 >>
提交
47f6760c
编写于
8月 28, 2015
作者:
S
Shirou WAKAYAMA
浏览文件
操作
浏览文件
下载
电子邮件补丁
差异文件
cpu[darwin]: use CGO to get CPUTimes. This is breaking. see #66.
上级
3c958a8e
变更
1
显示空白变更内容
内联
并排
Showing
1 changed file
with
102 addition
and
123 deletion
+102
-123
cpu/cpu_darwin.go
cpu/cpu_darwin.go
+102
-123
未找到文件。
cpu/cpu_darwin.go
浏览文件 @
47f6760c
...
...
@@ -2,104 +2,131 @@
package
cpu
/*
#include <stdlib.h>
#include <sys/sysctl.h>
#include <sys/mount.h>
#include <mach/mach_init.h>
#include <mach/mach_host.h>
#include <mach/host_info.h>
#include <libproc.h>
#include <mach/processor_info.h>
#include <mach/vm_map.h>
*/
import
"C"
import
(
"bytes"
"encoding/binary"
"fmt"
"io"
"os"
"os/exec"
"path/filepath"
"strconv"
"strings"
"unsafe"
)
common
"github.com/shirou/gopsutil/common"
// sys/resource.h
const
(
CPUser
=
0
CPNice
=
1
CPSys
=
2
CPIntr
=
3
CPIdle
=
4
CPUStates
=
5
)
var
HELPER_PATH
=
filepath
.
Join
(
os
.
Getenv
(
"HOME"
),
".gopsutil_cpu_helper"
)
// default value. from time.h
var
ClocksPerSec
=
float64
(
128
)
// enable cpu helper. It may become security problem.
// This env valiable approach will be changed.
const
HELPER_ENABLE_ENV
=
"ALLLOW_INSECURE_CPU_HELPER"
// these CPU times for darwin is borrowed from influxdb/telegraf.
var
ClocksPerSec
=
float64
(
100
)
func
perCPUTimes
()
([]
CPUTimesStat
,
error
)
{
var
(
count
C
.
mach_msg_type_number_t
cpuload
*
C
.
processor_cpu_load_info_data_t
ncpu
C
.
natural_t
)
func
init
()
{
out
,
err
:=
exec
.
Command
(
"/usr/bin/getconf"
,
"CLK_TCK"
)
.
Output
()
// ignore errors
if
err
==
nil
{
i
,
err
:=
strconv
.
ParseFloat
(
strings
.
TrimSpace
(
string
(
out
)),
64
)
if
err
==
nil
{
ClocksPerSec
=
float64
(
i
)
}
}
status
:=
C
.
host_processor_info
(
C
.
host_t
(
C
.
mach_host_self
()),
C
.
PROCESSOR_CPU_LOAD_INFO
,
&
ncpu
,
(
*
C
.
processor_info_array_t
)(
unsafe
.
Pointer
(
&
cpuload
)),
&
count
)
// adhoc compile on the host. Errors will be ignored.
// gcc is required to compile.
if
!
common
.
PathExists
(
HELPER_PATH
)
&&
os
.
Getenv
(
HELPER_ENABLE_ENV
)
==
"yes"
{
cmd
:=
exec
.
Command
(
"gcc"
,
"-o"
,
HELPER_PATH
,
"-x"
,
"c"
,
"-"
)
stdin
,
err
:=
cmd
.
StdinPipe
()
if
err
!=
nil
{
return
}
io
.
WriteString
(
stdin
,
cpu_helper_src
)
stdin
.
Close
()
cmd
.
Output
()
if
status
!=
C
.
KERN_SUCCESS
{
return
nil
,
fmt
.
Errorf
(
"host_processor_info error=%d"
,
status
)
}
}
func
CPUTimes
(
percpu
bool
)
([]
CPUTimesStat
,
error
)
{
// jump through some cgo casting hoops and ensure we properly free
// the memory that cpuload points to
target
:=
C
.
vm_map_t
(
C
.
mach_task_self_
)
address
:=
C
.
vm_address_t
(
uintptr
(
unsafe
.
Pointer
(
cpuload
)))
defer
C
.
vm_deallocate
(
target
,
address
,
C
.
vm_size_t
(
ncpu
))
// the body of struct processor_cpu_load_info
// aka processor_cpu_load_info_data_t
var
cpu_ticks
[
C
.
CPU_STATE_MAX
]
uint32
// copy the cpuload array to a []byte buffer
// where we can binary.Read the data
size
:=
int
(
ncpu
)
*
binary
.
Size
(
cpu_ticks
)
buf
:=
C
.
GoBytes
(
unsafe
.
Pointer
(
cpuload
),
C
.
int
(
size
))
bbuf
:=
bytes
.
NewBuffer
(
buf
)
var
ret
[]
CPUTimesStat
if
!
common
.
PathExists
(
HELPER_PATH
)
{
return
nil
,
fmt
.
Errorf
(
"could not get cpu time"
)
}
out
,
err
:=
exec
.
Command
(
HELPER_PATH
)
.
Output
()
for
i
:=
0
;
i
<
int
(
ncpu
);
i
++
{
err
:=
binary
.
Read
(
bbuf
,
binary
.
LittleEndian
,
&
cpu_ticks
)
if
err
!=
nil
{
return
ret
,
err
return
nil
,
err
}
for
_
,
line
:=
range
strings
.
Split
(
string
(
out
),
"
\n
"
)
{
f
:=
strings
.
Split
(
string
(
line
),
","
)
if
len
(
f
)
!=
5
{
continue
}
cpu
,
err
:=
strconv
.
ParseFloat
(
f
[
0
],
64
)
if
err
!=
nil
{
return
ret
,
err
}
// cpu:99 means total, so just ignore if percpu
if
(
percpu
&&
cpu
==
99
)
||
(
!
percpu
&&
cpu
!=
99
)
{
continue
}
user
,
err
:=
strconv
.
ParseFloat
(
f
[
1
],
64
)
if
err
!=
nil
{
return
ret
,
err
}
sys
,
err
:=
strconv
.
ParseFloat
(
f
[
2
],
64
)
if
err
!=
nil
{
return
ret
,
err
c
:=
CPUTimesStat
{
CPU
:
fmt
.
Sprintf
(
"cpu%d"
,
i
),
User
:
float64
(
cpu_ticks
[
C
.
CPU_STATE_USER
])
/
ClocksPerSec
,
System
:
float64
(
cpu_ticks
[
C
.
CPU_STATE_SYSTEM
])
/
ClocksPerSec
,
Nice
:
float64
(
cpu_ticks
[
C
.
CPU_STATE_NICE
])
/
ClocksPerSec
,
Idle
:
float64
(
cpu_ticks
[
C
.
CPU_STATE_IDLE
])
/
ClocksPerSec
,
}
idle
,
err
:=
strconv
.
ParseFloat
(
f
[
3
],
64
)
if
err
!=
nil
{
return
ret
,
err
ret
=
append
(
ret
,
c
)
}
nice
,
err
:=
strconv
.
ParseFloat
(
f
[
4
],
64
)
if
err
!=
nil
{
return
ret
,
err
return
ret
,
nil
}
func
allCPUTimes
()
([]
CPUTimesStat
,
error
)
{
var
count
C
.
mach_msg_type_number_t
=
C
.
HOST_CPU_LOAD_INFO_COUNT
var
cpuload
C
.
host_cpu_load_info_data_t
status
:=
C
.
host_statistics
(
C
.
host_t
(
C
.
mach_host_self
()),
C
.
HOST_CPU_LOAD_INFO
,
C
.
host_info_t
(
unsafe
.
Pointer
(
&
cpuload
)),
&
count
)
if
status
!=
C
.
KERN_SUCCESS
{
return
nil
,
fmt
.
Errorf
(
"host_statistics error=%d"
,
status
)
}
c
:=
CPUTimesStat
{
User
:
float64
(
user
/
ClocksPerSec
),
Nice
:
float64
(
nice
/
ClocksPerSec
),
System
:
float64
(
sys
/
ClocksPerSec
),
Idle
:
float64
(
idle
/
ClocksPerSec
),
}
if
!
percpu
{
c
.
CPU
=
"cpu-total"
}
else
{
c
.
CPU
=
fmt
.
Sprintf
(
"cpu%d"
,
uint16
(
cpu
))
CPU
:
"cpu-total"
,
User
:
float64
(
cpuload
.
cpu_ticks
[
C
.
CPU_STATE_USER
])
/
ClocksPerSec
,
System
:
float64
(
cpuload
.
cpu_ticks
[
C
.
CPU_STATE_SYSTEM
])
/
ClocksPerSec
,
Nice
:
float64
(
cpuload
.
cpu_ticks
[
C
.
CPU_STATE_NICE
])
/
ClocksPerSec
,
Idle
:
float64
(
cpuload
.
cpu_ticks
[
C
.
CPU_STATE_IDLE
])
/
ClocksPerSec
,
}
ret
=
append
(
ret
,
c
)
return
[]
CPUTimesStat
{
c
},
nil
}
func
CPUTimes
(
percpu
bool
)
([]
CPUTimesStat
,
error
)
{
if
percpu
{
return
perCPUTimes
()
}
return
ret
,
nil
return
allCPUTimes
()
}
// Returns only one CPUInfoStat on FreeBSD
...
...
@@ -174,51 +201,3 @@ func CPUInfo() ([]CPUInfoStat, error) {
return
append
(
ret
,
c
),
nil
}
const
cpu_helper_src
=
`
#include <mach/mach.h>
#include <mach/mach_error.h>
#include <stdio.h>
int main() {
natural_t cpuCount;
processor_info_array_t ia;
mach_msg_type_number_t ic;
kern_return_t error = host_processor_info(mach_host_self(),
PROCESSOR_CPU_LOAD_INFO, &cpuCount, &ia, &ic);
if (error) {
return error;
}
processor_cpu_load_info_data_t* cpuLoadInfo =
(processor_cpu_load_info_data_t*) ia;
unsigned int all[4];
// cpu_no,user,system,idle,nice
for (int cpu=0; cpu<cpuCount; cpu++){
printf("%d,", cpu);
for (int i=0; i<4; i++){
printf("%d", cpuLoadInfo[cpu].cpu_ticks[i]);
all[i] = all[i] + cpuLoadInfo[cpu].cpu_ticks[i];
if (i != 3){
printf(",");
}else{
printf("\n");
}
}
}
printf("99,");
for (int i=0; i<4; i++){
printf("%d", all[i]);
if (i != 3){
printf(",");
}else{
printf("\n");
}
}
vm_deallocate(mach_task_self(), (vm_address_t)ia, ic);
return error;
}
`
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录