我一直在研究实现特定流程的以下数据的最佳方法:
我决定使用OSHI(操作系统和硬件信息)API。 不幸的是,这个API并没有提供开箱即用的所需信息,它需要一些如何计算的基本知识,例如每个进程的CPU使用率。
我的问题是:如何按流程ID获取内存,磁盘和网络使用情况?
使用以下每个prcoess的cpu使用数据示例
例如:
获取claculator.exe运行进程的实际CPU使用率:
import oshi.SystemInfo;
import oshi.hardware.CentralProcessor;
import oshi.software.os.OSProcess;
import oshi.software.os.OperatingSystem;
public class processCPUusage {
public static void main(String[] args) throws InterruptedException {
OSProcess process;
long currentTime,previousTime = 0,timeDifference;
double cpu;
int pid = 7132;
SystemInfo si = new SystemInfo();
OperatingSystem os = si.getOperatingSystem();
CentralProcessor processor = si.getHardware().getProcessor();
int cpuNumber = processor.getLogicalProcessorCount();
boolean processExists = true;
while (processExists) {
process = os.getProcess(pid); // calculator.exe process id
if (process != null) {
// CPU
currentTime = process.getKernelTime() + process.getUserTime();
if (previousTime != -1) {
// If we have both a previous and a current time
// we can calculate the CPU usage
timeDifference = currentTime - previousTime;
cpu = (100d * (timeDifference / ((double) 1000))) / cpuNumber;
System.out.println(cpu);
}
previousTime = currentTime;
Thread.sleep(1000);
} else {
processExists = false;
}
}
}
}
我正在使用的框架 https://github.com/oshi/oshi/tree/master/src/site/markdown 演示了所需的功能,但缺少适当的例子
OSHI库+ slf4j
<dependency>
<groupId>com.github.dblock</groupId>
<artifactId>oshi-core</artifactId>
<version>3.4.0</version>
</dependency>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-api</artifactId>
<version>1.7.5</version>
</dependency>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-log4j12</artifactId>
<version>1.7.5</version>
</dependency>
答案 0 :(得分:2)
主要方法
public static void main(String[] args) {
int pid=8924;
for (int i = 0; i < 10; i++) {
diskUtilizationPerProcess(pid);
memoryUtilizationPerProcess(pid);
cpuUtilizationPerProcess(pid);
Util.sleep(5000);
}
}
磁盘/ IO:
public static void diskUtilizationPerProcess(int pid) {
/**
* ByteRead : Returns the number of bytes the process has read from disk.
* ByteWritten : Returns the number of bytes the process has written to disk.
*/
OSProcess process;
SystemInfo si = new SystemInfo();
OperatingSystem os = si.getOperatingSystem();
process = os.getProcess(pid);
System.out.println("\nDisk I/O Usage :");
System.out.println("I/O Reads: "+process.getBytesRead());
System.out.println("I/O Writes: "+process.getBytesWritten());
}
CPU使用率:
public static void cpuUtilizationPerProcess(int processId) {
/**
* User Time : Returns the number of milliseconds the process has executed in user mode.
* Kernel Time : Returns the number of milliseconds the process has executed in kernel/system mode.
*/
SystemInfo systemInfo = new SystemInfo();
CentralProcessor processor = systemInfo.getHardware().getProcessor();
int cpuNumber = processor.getLogicalProcessorCount();
//int processId = systemInfo.getOperatingSystem().getProcessId();
OSProcess process = systemInfo.getOperatingSystem().getProcess(processId);
long currentTime = process.getKernelTime() + process.getUserTime();
long timeDifference = currentTime - previousTime;
double processCpu = (100 * (timeDifference / 5000d)) / cpuNumber;
previousTime = currentTime;
System.out.println("\nCPU Usage :");
System.out.println("CPU : "+(int)processCpu+"%");
}
内存使用情况
public static void memoryUtilizationPerProcess(int pid) {
/**
* Resident Size : how much memory is allocated to that process and is in RAM
*/
OSProcess process;
SystemInfo si = new SystemInfo();
OperatingSystem os = si.getOperatingSystem();
process = os.getProcess(pid);
System.out.println("\nMemory Usage :");
System.out.println("Resident Size: "+process.getResidentSetSize());
}
答案 1 :(得分:1)
我是在您正在引用的OSHI中实现OSProcess类的人,并且已经在该项目的问题中与您进行了沟通。
虽然OSHI目前不提供OSProcess
接口中的所有功能,但它确实为您提供了WMI类的访问方法,这些方法将为您提供所需的所有信息。如果你看一下实现你正在使用的getProcess()
方法的WindowsOperatingSystem类,你可以使用WMIUtil
复制/修改代码,直接获取你需要的信息。
OSHI目前从Win32_Process WMI类中提取,但正如我在此问题上所提到的,从Win32_PerfRawData_PerfProc_Process获取信息可能更好(它提供了可用于直接的原始数据)计算)或Win32_PerfFormattedData_PerfProc_Process。在这些课程中,您可以找到:
CPU使用率
(注意,当名称显示“百分比”时,原始数据实际上包括递增“滴答”)
内存使用情况
磁盘使用情况,网络使用情况
在这些类中,磁盘和网络都合计为总计。 (同样,对于“原始数据”忽略“每秒”部分,它将增加数据总量)。
我认为Windows不会在每个进程的基础上跟踪磁盘与网络IO的差异。
你应该采取的步骤:
使用您想要的WMI字段名称定义逗号分隔的字符串
使用与字段名称匹配的类型定义ValueType
数组
同样的订单
执行Map<String, List<Object>> procs = WmiUtil.selectObjectsFrom(null, "Win32_PerfRawData_PerfProc_Process", processProperties, String.format("WHERE IdProcess=%d", pid), processPropertyTypes);
使用procs.get("FieldNameHere").get(0)