Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add Process disk usage (bytes read/written) #248

Closed
wants to merge 12 commits into from
1 change: 1 addition & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ doc-comment = "0.3"
[target.'cfg(windows)'.dependencies]
winapi = { version = "0.3", features = ["fileapi", "handleapi", "ioapiset", "minwindef", "pdh", "psapi", "synchapi", "sysinfoapi", "winbase", "winerror", "winioctl", "winnt", "oleauto", "wbemcli", "rpcdce", "combaseapi", "objidl", "objbase"] }
ntapi = "0.3"
winrt = { version = "0.6.0", features = ["windows-system"]}

[target.'cfg(not(any(target_os = "unknown", target_arch = "wasm32")))'.dependencies]
libc = "0.2"
Expand Down
12 changes: 12 additions & 0 deletions src/linux/process.rs
Original file line number Diff line number Diff line change
Expand Up @@ -124,6 +124,8 @@ pub struct Process {
/// Tasks run by this process.
pub tasks: HashMap<Pid, Process>,
pub(crate) stat_file: Option<File>,
pub(crate) read_bytes: u64,
pub(crate) written_bytes: u64,
}

impl ProcessExt for Process {
Expand Down Expand Up @@ -155,6 +157,8 @@ impl ProcessExt for Process {
HashMap::new()
},
stat_file: None,
read_bytes: 0,
written_bytes: 0,
}
}

Expand Down Expand Up @@ -215,6 +219,14 @@ impl ProcessExt for Process {
fn cpu_usage(&self) -> f32 {
self.cpu_usage
}

fn read_bytes(&self) -> u64 {
self.read_bytes
}

fn written_bytes(&self) -> u64 {
self.written_bytes
}
}

impl Drop for Process {
Expand Down
18 changes: 18 additions & 0 deletions src/linux/system.rs
Original file line number Diff line number Diff line change
Expand Up @@ -607,6 +607,7 @@ fn _get_process_data(
uptime,
now,
);
update_process_disk_activity(entry);
return Ok(None);
}

Expand Down Expand Up @@ -690,9 +691,26 @@ fn _get_process_data(
uptime,
now,
);
update_process_disk_activity(&mut p);
Ok(Some(p))
}

fn update_process_disk_activity(p: &mut Process) {
let path = PathBuf::from(format!("/proc/{}/io", p.pid));
let data = match get_all_data(&path, 16_384) {
Ok(d) => d,
Err(_) => return,
};
let data: Vec<Vec<&str>> = data.split("\n").map(|l| l.split(": ").collect()).collect();
for d in data.iter() {
if d[0] == "read_bytes" {
p.read_bytes = d[1].parse::<u64>().unwrap_or(0);
} else if d[0] == "write_bytes" {
p.written_bytes = d[1].parse::<u64>().unwrap_or(0);
}
}
}

fn copy_from_file(entry: &Path) -> Vec<String> {
match File::open(entry.to_str().unwrap_or("/")) {
Ok(mut f) => {
Expand Down
30 changes: 30 additions & 0 deletions src/mac/ffi.rs
Original file line number Diff line number Diff line change
Expand Up @@ -87,6 +87,11 @@ extern "C" {
// pub fn proc_name(pid: i32, buf: *mut i8, bufsize: u32) -> i32;
}

#[link(name = "proc", kind = "dylib")]
extern "C" {
pub fn proc_pid_rusage(pid: c_int, flavor: c_int, buffer: *mut c_void) -> c_int;
}

// TODO: waiting for https://github.com/rust-lang/libc/pull/678
macro_rules! cfg_if {
($(
Expand Down Expand Up @@ -342,6 +347,31 @@ pub struct xsw_usage {
pub xsu_encrypted: boolean_t,
}

//https://github.com/andrewdavidmackenzie/libproc-rs/blob/master/src/libproc/pid_rusage.rs
#[repr(C)]
#[derive(Debug, Default)]
pub struct RUsageInfoV2 {
pub ri_uuid: [u8; 16],
pub ri_user_time: u64,
pub ri_system_time: u64,
pub ri_pkg_idle_wkups: u64,
pub ri_interrupt_wkups: u64,
pub ri_pageins: u64,
pub ri_wired_size: u64,
pub ri_resident_size: u64,
pub ri_phys_footprint: u64,
pub ri_proc_start_abstime: u64,
pub ri_proc_exit_abstime: u64,
pub ri_child_user_time: u64,
pub ri_child_system_time: u64,
pub ri_child_pkg_idle_wkups: u64,
pub ri_child_interrupt_wkups: u64,
pub ri_child_pageins: u64,
pub ri_child_elapsed_abstime: u64,
pub ri_diskio_bytesread: u64,
pub ri_diskio_byteswritten: u64,
}

//pub const HOST_CPU_LOAD_INFO_COUNT: usize = 4;
//pub const HOST_CPU_LOAD_INFO: u32 = 3;
pub const KERN_SUCCESS: kern_return_t = 0;
Expand Down
47 changes: 40 additions & 7 deletions src/mac/process.rs
Original file line number Diff line number Diff line change
Expand Up @@ -149,14 +149,12 @@ pub struct Process {
///
/// This is very likely this one that you want instead of `process_status`.
pub status: Option<ThreadStatus>,
pub(crate) read_bytes: u64,
pub(crate) written_bytes: u64,
}

impl Process {
pub(crate) fn new_empty(
pid: Pid,
exe: PathBuf,
name: String,
) -> Process {
pub(crate) fn new_empty(pid: Pid, exe: PathBuf, name: String) -> Process {
Process {
name,
pid,
Expand All @@ -179,6 +177,8 @@ impl Process {
gid: 0,
process_status: ProcessStatus::Unknown(0),
status: None,
read_bytes: 0,
written_bytes: 0,
}
}

Expand Down Expand Up @@ -214,6 +214,8 @@ impl Process {
gid: 0,
process_status: ProcessStatus::Unknown(0),
status: None,
read_bytes: 0,
written_bytes: 0,
}
}
}
Expand Down Expand Up @@ -242,6 +244,8 @@ impl ProcessExt for Process {
gid: 0,
process_status: ProcessStatus::Unknown(0),
status: None,
read_bytes: 0,
written_bytes: 0,
}
}

Expand Down Expand Up @@ -300,6 +304,14 @@ impl ProcessExt for Process {
fn cpu_usage(&self) -> f32 {
self.cpu_usage
}

fn read_bytes(&self) -> u64 {
self.read_bytes
}

fn written_bytes(&self) -> u64 {
self.written_bytes
}
}

#[allow(unused_must_use)]
Expand Down Expand Up @@ -422,6 +434,7 @@ pub(crate) fn update_process(

p.memory = task_info.pti_resident_size >> 10; // divide by 1024
p.virtual_memory = task_info.pti_virtual_size >> 10; // divide by 1024
update_proc_disk_activity(p);
return Ok(None);
}

Expand All @@ -435,7 +448,11 @@ pub(crate) fn update_process(
) != mem::size_of::<libc::proc_bsdinfo>() as _
{
let mut buffer: Vec<u8> = Vec::with_capacity(ffi::PROC_PIDPATHINFO_MAXSIZE as _);
match ffi::proc_pidpath(pid, buffer.as_mut_ptr() as *mut _, ffi::PROC_PIDPATHINFO_MAXSIZE) {
match ffi::proc_pidpath(
pid,
buffer.as_mut_ptr() as *mut _,
ffi::PROC_PIDPATHINFO_MAXSIZE,
) {
x if x > 0 => {
buffer.set_len(x as _);
let tmp = String::from_utf8_unchecked(buffer);
Expand Down Expand Up @@ -606,11 +623,27 @@ pub(crate) fn update_process(
p.uid = info.pbi_uid;
p.gid = info.pbi_gid;
p.process_status = ProcessStatus::from(info.pbi_status);

update_proc_disk_activity(&mut p);
Ok(Some(p))
}
}

fn update_proc_disk_activity(p: &mut Process) {
let mut pidrusage = ffi::RUsageInfoV2::default();
let ptr = &mut pidrusage as *mut _ as *mut c_void;
let retval: i32;
unsafe {
retval = ffi::proc_pid_rusage(p.pid() as c_int, 2, ptr);
}

if retval < 0 {
panic!("proc_pid_rusage failed: {:?}", retval);
} else {
p.read_bytes = pidrusage.ri_diskio_bytesread;
p.written_bytes = pidrusage.ri_diskio_byteswritten;
}
}

pub(crate) fn get_proc_list() -> Option<Vec<Pid>> {
let count = unsafe { ffi::proc_listallpids(::std::ptr::null_mut(), 0) };
if count < 1 {
Expand Down
18 changes: 4 additions & 14 deletions src/mac/system.rs
Original file line number Diff line number Diff line change
Expand Up @@ -288,15 +288,9 @@ impl SystemExt for System {
let entries: Vec<Process> = {
let wrap = &Wrap(UnsafeCell::new(&mut self.process_list));
pids.par_iter()
.flat_map(|pid| {
match update_process(
wrap,
*pid,
arg_max as size_t,
) {
Ok(x) => x,
Err(_) => None,
}
.flat_map(|pid| match update_process(wrap, *pid, arg_max as size_t) {
Ok(x) => x,
Err(_) => None,
})
.collect()
};
Expand All @@ -311,11 +305,7 @@ impl SystemExt for System {
let arg_max = get_arg_max();
match {
let wrap = Wrap(UnsafeCell::new(&mut self.process_list));
update_process(
&wrap,
pid,
arg_max as size_t,
)
update_process(&wrap, pid, arg_max as size_t)
} {
Ok(Some(p)) => {
self.process_list.insert(p.pid(), p);
Expand Down
3 changes: 2 additions & 1 deletion src/sysinfo.rs
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@
#![crate_name = "sysinfo"]
#![crate_type = "lib"]
#![crate_type = "rlib"]
#![deny(missing_docs)]
#![warn(missing_docs)]
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please don't change this one.

//#![deny(warnings)]
#![allow(unknown_lints)]

Expand All @@ -69,6 +69,7 @@ cfg_if! {
use windows as sys;
extern crate winapi;
extern crate ntapi;
extern crate winrt;
} else if #[cfg(unix)] {
mod linux;
use linux as sys;
Expand Down
6 changes: 6 additions & 0 deletions src/traits.rs
Original file line number Diff line number Diff line change
Expand Up @@ -93,6 +93,12 @@ pub trait ProcessExt {

/// Returns the total CPU usage.
fn cpu_usage(&self) -> f32;

/// Returns number of bytes read from disk
fn read_bytes(&self) -> u64;

/// Returns number of bytes written to disk
fn written_bytes(&self) -> u64;
}

/// Contains all the methods of the `Processor` struct.
Expand Down
Loading