mprober_lib/process/
process_stat.rs1use std::{io::ErrorKind, path::Path, str::from_utf8_unchecked};
2
3use page_size::get as get_page_size;
4
5use crate::{
6 process::ProcessState,
7 scanner_rust::{
8 generic_array::typenum::{U192, U32},
9 Scanner, ScannerError,
10 },
11};
12
13#[derive(Default, Debug, Clone)]
14pub struct ProcessStat {
15 pub state: ProcessState,
16 pub comm: String,
17 pub ppid: u32,
18 pub pgrp: u32,
19 pub session: u32,
20 pub tty_nr_major: u8,
21 pub tty_nr_minor: u32,
22 pub tpgid: Option<u32>,
23 pub utime: u32,
24 pub stime: u32,
25 pub cutime: u32,
26 pub cstime: u32,
27 pub priority: i8,
28 pub nice: i8,
29 pub num_threads: usize,
30 pub starttime: u64,
31 pub vsize: usize,
33 pub rss: usize,
35 pub rsslim: usize,
36 pub processor: usize,
37 pub rt_priority: u8,
38 pub shared: usize,
40 pub rss_anon: usize,
42}
43
44pub fn get_process_stat(pid: u32) -> Result<ProcessStat, ScannerError> {
54 let mut stat = ProcessStat::default();
55
56 let stat_path = Path::new("/proc").join(pid.to_string()).join("stat");
57
58 let mut sc: Scanner<_, U192> = Scanner::scan_path2(stat_path)?;
59
60 sc.drop_next()?.ok_or(ErrorKind::UnexpectedEof)?;
61
62 sc.drop_next_until("(")?.ok_or(ErrorKind::UnexpectedEof)?;
63
64 loop {
65 let comm = sc.next_raw()?.ok_or(ErrorKind::UnexpectedEof)?;
66
67 if comm.ends_with(b")") {
68 stat.comm.push_str(unsafe { from_utf8_unchecked(&comm[..(comm.len() - 1)]) });
69 break;
70 } else {
71 stat.comm.push_str(unsafe { from_utf8_unchecked(comm.as_ref()) });
72 }
73 }
74
75 stat.state = ProcessState::from_str(unsafe {
76 from_utf8_unchecked(&sc.next_raw()?.ok_or(ErrorKind::UnexpectedEof)?)
77 })
78 .ok_or(ErrorKind::InvalidData)?;
79
80 stat.ppid = sc.next_u32()?.ok_or(ErrorKind::UnexpectedEof)?;
81 stat.pgrp = sc.next_u32()?.ok_or(ErrorKind::UnexpectedEof)?;
82 stat.session = sc.next_u32()?.ok_or(ErrorKind::UnexpectedEof)?;
83
84 {
85 let tty_nr = sc.next_u32()?.ok_or(ErrorKind::UnexpectedEof)?;
86
87 stat.tty_nr_major = (tty_nr >> 8) as u8;
88 stat.tty_nr_minor = ((tty_nr >> 20) << 8) | (tty_nr & 0xFF);
89 }
90
91 {
92 let tpgid = sc.next_i32()?.ok_or(ErrorKind::UnexpectedEof)?;
93
94 if tpgid >= 0 {
95 stat.tpgid = Some(tpgid as u32);
96 }
97 }
98
99 for _ in 0..5 {
100 sc.drop_next()?.ok_or(ErrorKind::UnexpectedEof)?;
101 }
102
103 stat.utime = sc.next_u32()?.ok_or(ErrorKind::UnexpectedEof)?;
104 stat.stime = sc.next_u32()?.ok_or(ErrorKind::UnexpectedEof)?;
105 stat.cutime = sc.next_u32()?.ok_or(ErrorKind::UnexpectedEof)?;
106 stat.cstime = sc.next_u32()?.ok_or(ErrorKind::UnexpectedEof)?;
107 stat.priority = sc.next_i8()?.ok_or(ErrorKind::UnexpectedEof)?;
108 stat.nice = sc.next_i8()?.ok_or(ErrorKind::UnexpectedEof)?;
109 stat.num_threads = sc.next_usize()?.ok_or(ErrorKind::UnexpectedEof)?;
110
111 sc.drop_next()?.ok_or(ErrorKind::UnexpectedEof)?;
112
113 stat.starttime = sc.next_u64()?.ok_or(ErrorKind::UnexpectedEof)?;
114 stat.vsize = sc.next_usize()?.ok_or(ErrorKind::UnexpectedEof)?;
115 stat.rss = sc.next_usize()?.ok_or(ErrorKind::UnexpectedEof)? * get_page_size();
116 stat.rsslim = sc.next_usize()?.ok_or(ErrorKind::UnexpectedEof)?;
117
118 for _ in 0..13 {
119 sc.drop_next()?.ok_or(ErrorKind::UnexpectedEof)?;
120 }
121
122 stat.processor = sc.next_usize()?.ok_or(ErrorKind::UnexpectedEof)?;
123 stat.rt_priority = sc.next_u8()?.ok_or(ErrorKind::UnexpectedEof)?;
124
125 drop(sc);
126
127 let statm_path = Path::new("/proc").join(pid.to_string()).join("statm");
128
129 let mut sc: Scanner<_, U32> = Scanner::scan_path2(statm_path)?;
130
131 for _ in 0..2 {
132 sc.drop_next()?.ok_or(ErrorKind::UnexpectedEof)?;
133 }
134
135 stat.shared = sc.next_usize()?.ok_or(ErrorKind::UnexpectedEof)? * get_page_size();
136
137 stat.rss_anon = stat.rss - stat.shared;
138
139 Ok(stat)
140}