#linux #linux-kernel #zero-allocation #procfs #parse #parser #meminfo

linux-meminfo

一个高效的、无分配/proc/meminfo 解析库

1 个不稳定版本

0.1.0 2023年11月30日

#466 in Unix API

GPL-3.0-only

45KB
601 代码行,不含注释

Linux MemInfo

GitHub source size GitHub open issues GitHub open pull requests GitHub sponsors GitHub license Crates.io downloads Crates.io version

此库提供了对Linux内核在proc伪文件系统中放置的meminfo伪文件的低级和简单访问(更多信息,请参阅proc 手册页)。

公共API围绕着MemInfo类型构建,这是一个负责检索系统内存信息的结构体。调用其构造函数将打开/proc/meminfo伪文件并将数据读取到内部缓冲区。由于MemInfo同时拥有打开的文件和其数据的缓冲区,因此可以在从伪文件中读取、管理以及解析缓冲区数据之间分离关注点。

负责解析/proc/meminfo条目的解析器实现仅对字符串切片进行操作,仅拥有对伪文件缓冲字节的引用。这允许进行高效、零分配的解析。

示例

以下示例展示了MemInfo API的最基本用法。首先,我们构造一个新的实例,这相当于打开/proc/meminfo并将其读取到内部缓冲区;然后我们调用MemInfo::parse,它返回一个解析条目的惰性迭代器,在这种情况下由MemInfoEntry类型表示。迭代器是惰性的,意味着它会在每次调用next方法时解析一个新的条目。换句话说:您只需为解析的条目付费。

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(())
}

用户可能有不同的用例,需要定期检索/proc/meminfo伪文件中的特定条目集。MemInfo::parse_extended有效地解决了这个需求,通过扩展解析条目以包含有关它们在文件流中占用的字节范围的额外信息。此功能允许用户根据需要选择性地读取和解析特定的条目。此外,通过这种方式,内部缓冲区可以缩小到读取此类条目所需的容量,从而减少程序的运行时内存占用。

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)?;
    }
}

用法

要在您的项目中使用此库,请在项目根目录中运行以下命令

cargo add linux-meminfo

功能

默认情况下,MemInfoEntryMemInfoEntryExtended 构造函数会在解析 /proc/meminfo 数据时进行 UTF-8 验证。不正确的数据会导致程序崩溃。但是,启用 utf8-unchecked 功能可以移除此类验证,从而可能提高解析性能。为此,新构造函数使用不安全代码,因此用户应意识到不正确的 /proc/meminfo 数据会导致未定义的行为。

要启用此功能,请在项目根目录中运行以下命令

cargo add linux-meminfo --features=utf8-unchecked

许可协议

此库根据 GPLv3 许可协议许可。

贡献

欢迎并鼓励任何形式的贡献。

无运行时依赖

功能