diff --git a/examples/shm.rs b/examples/shm.rs new file mode 100644 index 00000000..5123681e --- /dev/null +++ b/examples/shm.rs @@ -0,0 +1,33 @@ +#![allow(clippy::print_literal)] + +extern crate procfs; + +/// List processes using posix shared memory segments + +fn main() { + let shared_memory_vec = procfs::Shm::new().unwrap(); + + for shared_memory in &shared_memory_vec { + println!("key: {}, shmid: {}", shared_memory.key, shared_memory.shmid); + println!("============"); + + for prc in procfs::process::all_processes().unwrap() { + match prc.smaps() { + Ok(memory_maps) => { + for (memory_map, memory_map_data) in &memory_maps { + match memory_map.pathname { + procfs::process::MMapPath::Vsys(key) => { + if key == shared_memory.key && memory_map.inode == shared_memory.shmid { + println!("{}: {:?}", prc.pid, prc.cmdline().unwrap()); + } + } + _ => (), + } + } + } + Err(_) => continue, + } + } + println!(""); + } +} diff --git a/src/lib.rs b/src/lib.rs index 38d125f7..f7950e0e 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -266,6 +266,9 @@ pub mod process; mod meminfo; pub use crate::meminfo::*; +mod sysvipc_shm; +pub use crate::sysvipc_shm::*; + pub mod net; mod cpuinfo; diff --git a/src/sysvipc_shm.rs b/src/sysvipc_shm.rs new file mode 100644 index 00000000..b7e0b39e --- /dev/null +++ b/src/sysvipc_shm.rs @@ -0,0 +1,109 @@ +use std::io; + +use libc::pid_t; + +use super::{FileWrapper, ProcResult}; +use std::str::FromStr; + +/// A shared memory segment parsed from `/proc/sysvipc/shm` +/// Relation with `[crate::process::process::MMapPath::Vsys]` +#[derive(Debug, Clone)] +#[allow(non_snake_case)] +pub struct Shm { + /// Segment key + pub key: i32, + /// Segment ID, unique + pub shmid: u64, + /// Access permissions, as octal + pub perms: u16, + /// Size in bytes + pub size: u32, + /// Creator PID + pub cpid: pid_t, + /// Last operator PID + pub lpid: pid_t, + /// Number of attached processes + pub nattch: u32, + /// User ID + pub uid: u16, + /// Group ID + pub gid: u16, + /// Creator UID + pub cuid: u16, + /// Creator GID + pub cgid: u16, + /// Time of last `shmat` (attach), epoch + pub atime: u64, + /// Time of last `shmdt` (detach), epoch + pub dtime: u64, + /// Time of last permission change, epoch + pub ctime: u64, + /// Current part of the shared memory resident in memory + pub rss: u64, + /// Current part of the shared memory in SWAP + pub swap: u64, +} + +impl Shm { + /// Reads and parses the `/proc/sysvipc/shm`, returning an error if there are problems. + pub fn new() -> ProcResult> { + let f = FileWrapper::open("/proc/sysvipc/shm")?; + + Shm::from_reader(f) + } + + /// Get Meminfo from a custom Read instead of the default `/proc/sysvipc/shm`. + pub fn from_reader(r: R) -> ProcResult> { + use std::io::{BufRead, BufReader}; + + let reader = BufReader::new(r); + let mut vec = Vec::new(); + + // See printing code here: + // https://elixir.bootlin.com/linux/latest/source/ipc/shm.c#L1737 + for line in reader.lines().skip(1) { + let line = expect!(line); + let mut s = line.split_whitespace(); + + let key = expect!(i32::from_str(expect!(s.next()))); + let shmid = expect!(u64::from_str(expect!(s.next()))); + let perms = expect!(u16::from_str(expect!(s.next()))); + let size = expect!(u32::from_str(expect!(s.next()))); + let cpid = expect!(pid_t::from_str(expect!(s.next()))); + let lpid = expect!(pid_t::from_str(expect!(s.next()))); + let nattch = expect!(u32::from_str(expect!(s.next()))); + let uid = expect!(u16::from_str(expect!(s.next()))); + let gid = expect!(u16::from_str(expect!(s.next()))); + let cuid = expect!(u16::from_str(expect!(s.next()))); + let cgid = expect!(u16::from_str(expect!(s.next()))); + let atime = expect!(u64::from_str(expect!(s.next()))); + let dtime = expect!(u64::from_str(expect!(s.next()))); + let ctime = expect!(u64::from_str(expect!(s.next()))); + let rss = expect!(u64::from_str(expect!(s.next()))); + let swap = expect!(u64::from_str(expect!(s.next()))); + + let shm = Shm { + key, + shmid, + perms, + size, + cpid, + lpid, + nattch, + uid, + gid, + cuid, + cgid, + atime, + dtime, + ctime, + rss, + swap, + }; + + vec.push(shm); + } + + Ok(vec) + } +}