procfs

repository·master·Indexed 19 days ago

https://github.com/eminence/procfs

A Rust library providing a structured interface to the Linux /proc pseudo-filesystem. It enables programmatic access to process and kernel information, including process hierarchy, memory usage, network interface statistics, disk I/O, mountpoints, CGroup controllers, and the kernel keyring facility.

Tokens
24.9K
Snippets
100
Records
119
Agent score
65%

What's inside procfs

  1. Overview of procfs

    master
    procfs is a Rust interface to the Linux proc pseudo-filesystem (typically mounted at /proc). It allows developers to programmatically access kernel and process information. While the crate aims for full feature completeness, not all files in /proc are currently exposed. For a list of supported files, refer to the support.md file in the repository.
  2. Manage key timeouts with KeyTimeout

    master

    The KeyTimeout enum defines how long a key remains valid. It can be set to Permanent, Expired, or a specific Timeout(Duration).

    When parsing from procfs string formats, timeouts are represented as:

    • perm: KeyTimeout::Permanent
    • expd: KeyTimeout::Expired
    • <value><unit>: A duration where the unit can be s (seconds), m (minutes), h (hours), d (days), or w (weeks).
    // Example timeout strings and their mappings:
    // "perm" -> Permanent
    // "2w"   -> Timeout(Duration of 2 weeks)
    // "14d"  -> Timeout(Duration of 14 days)
  3. Understand the `Current` and `CurrentSI` traits

    master

    The crate uses several traits to simplify accessing the 'current' state of the system:

    • Current: Used for types that can be parsed directly from their standard system file path. Calling .current() will parse the file defined by const PATH.
    • CurrentSI: Used for types that require SystemInfo to parse their file. Calling .current() will use the global current_system_info().
    • WithCurrentSystemInfo: An extension trait that allows you to call .get() on a type to automatically use the current system information for parsing.
  4. Configure Cargo features for procfs

    master

    The following Cargo features can be enabled to extend the functionality of procfs:

    • chrono (Default): Enables methods that return values as DateTime objects.
    • flate2 (Default): Enables parsing gzip compressed /proc/config.gz via procfs::kernel_config.
    • backtrace: Provides a stack trace whenever an InternalError is raised.
    • serde1: Enables serialization and deserialization for most structs using serde 1.0. (Requires Rust > 1.70.0).
  5. Iterate over process tasks (threads)

    master

    A process can contain multiple tasks (threads). You can iterate over them using Process::tasks().

    Warning: The TasksIter is lazy. It does not take a snapshot. New tasks created during iteration will appear, and tasks that terminate during iteration might not appear. To get a consistent view, collect the tasks into a Vec as quickly as possible.

    let proc = procfs::process::Process::myself()?;
    
    // Snapshot approach: collect immediately to avoid laziness issues
    let threads: Vec<_> = proc.tasks()?
        .flatten()
        .map(|t| t.stat().unwrap().comm)
        .collect();
  6. Understand ProcessesIter behavior and resource usage

    master

    The ProcessesIter struct provides a lazy iterator over the system's processes.

    Key considerations:

    • Laziness: It is a lazy iterator. To get a near-instantaneous view of the system, consume the iterator quickly.
    • File Descriptors: Each Process struct produced by the iterator holds an open file descriptor to its corresponding /proc/<pid> directory. Be mindful of file descriptor limits if you collect a large number of Process instances without dropping them.
  7. Parse procfs data using FromRead and FromBufRead traits

    master

    The procfs-core crate uses several traits to allow types to be instantiated from raw data sources. Most data structures in this crate implement these traits.

    • FromRead: Allows parsing from any type implementing std::io::Read. It provides a helper method from_file(path) to open and parse a file directly.
    • FromBufRead: Allows parsing from any type implementing std::io::BufRead (more efficient for line-based parsing).
    • FromReadSI / FromBufReadSI: Variants of the above that also accept a SystemInfo object, which is required for calculations that depend on system-specific constants like ticks_per_second or page_size.
    use procfs_core::prelude::*;
    
    // Example: Parsing a type from a file (if the type implements FromRead)
    let my_data = MyProcfsType::from_file("/proc/stat")?; 
    
    // Example: Parsing from a buffer (if the type implements FromBufRead)
    let buffer = b"some procfs data";
    let my_data = MyProcfsType::from_buf_read(buffer)?;
  8. Understand the `Status` struct for process information

    master

    The Status struct provides a comprehensive view of process information parsed from the /proc/<pid>/status file.

    Key Characteristics

    • Kernel Dependency: Not all fields are available in every kernel. Fields that depend on specific kernel versions or configurations are wrapped in Option<T>. Always handle None values to ensure your application is robust across different Linux environments.
    • Extensibility: The struct is marked #[non_exhaustive], meaning new fields may be added in future versions without a major semver bump.
    • Serialization: If the serde1 feature is enabled, Status implements Serialize and Deserialize.

    Core Data Categories

    • Identifiers: name, tgid (Thread Group ID/PID), pid (Thread ID), ppid (Parent PID), tracerpid.
    • Credentials: UIDs (ruid, euid, suid, fuid) and GIDs (rgid, egid, sgid, fgid), plus supplementary groups.
    • Memory Usage: Various metrics in kibibytes (kB), such as vmsize (Virtual memory), vmrss (Resident set size), vmpeak (Peak virtual memory), and vmpin (Pinned memory).
    • Signals: Information on pending signals (sigpnd, shdpnd), blocked signals (sigblk), and queued signals (sigq).
    • Capabilities: Bitmasks for various capability sets like capinh (inheritable), capprm (permitted), capeff (effective), capbnd (bounding), and capamb (ambient).
    • Scheduling & Affinity: cpus_allowed (bitmask) and cpus_allowed_list (range list), as well as context switch counts (voluntary_ctxt_switches, nonvoluntary_ctxt_switches).
  9. Understand the Limit and LimitValue types

    master

    Resource limits are represented using two hierarchical types:

    1. Limit: A struct containing two LimitValue fields:

      • soft_limit: The current effective limit.
      • hard_limit: The ceiling that the soft limit can be raised to (by a privileged user).
    2. LimitValue: An enum representing the actual value of a limit:

      • Unlimited: Indicates there is no restriction on the resource.
      • Value(u64): A specific numeric limit (e.g., bytes, seconds, or microseconds).
  10. Understand BinFmtEntry and BinFmtData

    master

    A BinFmtEntry represents a registered binary format. It contains metadata about how the kernel should handle specific binary types.

    An entry's matching logic is contained within the data field, which is a BinFmtData enum:

    • BinFmtData::Extension(String): The format is triggered by a specific file extension (e.g., .hello).
    • BinFmtData::Magic { offset, magic, mask }: The format is triggered by matching a specific byte sequence (magic) at a specific offset within the binary, filtered by a mask.
  11. Understand KeyFlags in the kernel keyring facility

    master

    The KeyFlags bitflags represent the current state of a kernel key. These flags are used to identify if a key is instantiated, revoked, dead, or under construction. When parsing from string representations (like those found in /proc/keys), the flags are identified by specific characters: I (INSTANTIATED), R (REVOKED), D (DEAD), Q (QUOTA), U (UNDER_CONSTRUCTION), N (NEGATIVE), and i (INVALID).

    // Example of how flags are represented in string format
    // 'I' = INSTANTIATED, 'R' = REVOKED
    let flags = KeyFlags::from_str("IR");