//! Lectura de `/proc//` para telemetría. Sin invocar binarios //! externos (`ps`, `free`): syscalls + lectura directa de procfs. /// RSS en bytes desde `/proc//status` (línea `VmRSS:`). /// Devuelve 0 si el proceso ya no existe o la línea falta. pub fn read_mem_bytes(pid: i32) -> u64 { let path = format!("/proc/{pid}/status"); let Ok(content) = std::fs::read_to_string(&path) else { return 0; }; for line in content.lines() { if let Some(rest) = line.strip_prefix("VmRSS:") { // formato: "VmRSS:\t 1234 kB" let kb: u64 = rest .split_whitespace() .next() .and_then(|s| s.parse().ok()) .unwrap_or(0); return kb * 1024; } } 0 } /// Número de threads desde `/proc//status` (línea `Threads:`). /// Devuelve 0 si el proceso ya no existe. pub fn read_thread_count(pid: i32) -> u32 { let path = format!("/proc/{pid}/status"); let Ok(content) = std::fs::read_to_string(&path) else { return 0; }; for line in content.lines() { if let Some(rest) = line.strip_prefix("Threads:") { return rest.trim().parse().unwrap_or(0); } } 0 } /// `true` si `/proc/` existe (el proceso, vivo o zombie, está presente). pub fn proc_exists(pid: i32) -> bool { std::path::Path::new(&format!("/proc/{pid}")).exists() } #[cfg(test)] mod tests { use super::*; #[test] fn self_has_positive_rss_and_threads() { let me = std::process::id() as i32; assert!(read_mem_bytes(me) > 0, "el propio proceso debe tener RSS"); assert!(read_thread_count(me) >= 1); assert!(proc_exists(me)); } #[test] fn nonexistent_pid_is_zero() { // PID improbable de existir. assert_eq!(read_mem_bytes(2_000_000_000), 0); assert!(!proc_exists(2_000_000_000)); } }