1 unstable release
0.1.0 | Nov 30, 2023 |
---|
#725 in Unix APIs
45KB
601 lines
Linux MemInfo
This library provides easy and low level access to meminfo
, the pseudofile
placed by the Linux kernel inside the proc
pseudo-filesystem (for more
information, see the proc
manpage).
The public API is built around the MemInfo
type, a struct responsible for
retrieving memory-related information about the system. Calling its constructor
opens the /proc/meminfo
pseudofile and reads its data into an internal buffer.
Having MemInfo
to own both the open file and a buffer of its data allows
separation of concerns between reading from the pseudofile, managing and
parsing the buffered data.
The parser implementation responsible for parsing /proc/meminfo
entries
works exclusively on string slices, just owning a reference to the pseudofile
buffered bytes. This allows for efficient, zero-allocation parsing.
Examples
The following example shows the most basic usage of the MemInfo
API. First
we construct a new instance, which translates to /proc/meminfo
being opened
and read into the internal buffer; then we call the MemInfo::parse
, which
returns a lazy iterator over parsed entries, in this case represented by
the MemInfoEntry
type. The iterator being lazy meaning it parses a new
entry on each call to the next
method. In other words: you only pay for the
entries you parse.
use std::error;
use meminfo::MemInfo;
fn main() -> Result<(), Box<dyn error::Error>> {
let mut meminfo = MemInfo::new()?;
let mut entries = meminfo.parse();
let mem_total = entries.next().unwrap();
assert_eq!("MemTotal", mem_total.label());
assert_eq!(Some("kB"), mem_total.unit());
println!("System's total usable RAM: {}kB", mem_total.size()?);
Ok(())
}
Users may have distinct use cases that call for regular retrieval of a
particular set of entries within the /proc/meminfo
pseudofile. The
MemInfo::parse_extended
efficiently addresses this requirement, extending
parsed entries with additional information pertaining to the byte range they
occupy in the file stream. This functionality allows users to selectively read
and parse specific entries as needed. Also, this way, the internal buffer can
be shrank to the capacity required to read in such entries, reducing the runtime
memory footprint of the program.
use std::io::SeekFrom;
use std::time::Duration;
use std::{error, thread};
use meminfo::{MemInfo, MemInfoError};
#[derive(Debug)]
struct MemAvailable {
size: usize,
start_pos: usize,
}
impl MemAvailable {
fn new(meminfo: &mut MemInfo) -> Result<Self, MemInfoError> {
let mut entries = meminfo.parse_extended().skip(2);
let mem_available = entries.next().unwrap();
assert_eq!("MemAvailable", mem_available.label());
assert_eq!(Some("kB"), mem_available.unit());
let size = mem_available.size().unwrap();
let start_pos = mem_available.start_pos();
let capacity = mem_available.required_capacity();
drop(entries);
meminfo.clear();
meminfo.shrink_to(capacity);
Ok(MemAvailable { size, start_pos })
}
fn fetch(&mut self, meminfo: &mut MemInfo) -> Result<(), MemInfoError> {
let seek_pos = SeekFrom::Start(self.start_pos as u64);
meminfo.seek(seek_pos)?;
meminfo.clear();
meminfo.read()?;
let entry = meminfo.parse().next().unwrap();
self.size = entry.size().unwrap();
Ok(())
}
}
fn main() -> Result<(), Box<dyn error::Error>> {
let mut meminfo = MemInfo::new()?;
let mut mem_available = MemAvailable::new(&mut meminfo)?;
loop {
println!("System's available RAM: {}kB", mem_available.size);
thread::sleep(Duration::from_secs(2));
mem_available.fetch(&mut meminfo)?;
}
}
Usage
To use this library in your project, run the following command in your project root directory:
cargo add linux-meminfo
Features
By default, the MemInfoEntry
and MemInfoEntryExtended
constructors perform
UTF-8 validation on /proc/meminfo
parsed data. Malformed data would cause
a panic in this case. However, enabling the utf8-unchecked
feature removes
such validation, potentially increasing parsing performance. To achieve this,
the new constructors make use of unsafe code, thus the user should be aware
that malformed /proc/meminfo
data would cause undefined behaviour.
To opt-in such feature, run the following command in your the project root directory:
cargo add linux-meminfo --features=utf8-unchecked
License
This library is licensed under the terms of the GPLv3 license.
Contributions
Any contribution is welcome and encouraged.