Merge pull request #8951 from mattsu2020/uucore-memory

refactor(uucore): integrate procfs for Linux memory parsing
This commit is contained in:
Sylvestre Ledru 2025-10-20 10:12:02 +02:00 committed by GitHub
commit 8e7c6b01a4
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
4 changed files with 390 additions and 217 deletions

25
Cargo.lock generated
View file

@ -2331,6 +2331,30 @@ dependencies = [
"unicode-ident",
]
[[package]]
name = "procfs"
version = "0.18.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "25485360a54d6861439d60facef26de713b1e126bf015ec8f98239467a2b82f7"
dependencies = [
"bitflags 2.9.1",
"chrono",
"flate2",
"procfs-core",
"rustix",
]
[[package]]
name = "procfs-core"
version = "0.18.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e6401bf7b6af22f78b563665d15a22e9aef27775b79b149a66ca022468a4e405"
dependencies = [
"bitflags 2.9.1",
"chrono",
"hex",
]
[[package]]
name = "quote"
version = "1.0.41"
@ -4329,6 +4353,7 @@ dependencies = [
"num-traits",
"number_prefix",
"os_display",
"procfs",
"selinux",
"sha1",
"sha2",

528
fuzz/Cargo.lock generated

File diff suppressed because it is too large Load diff

View file

@ -101,6 +101,9 @@ xattr = { workspace = true, optional = true }
[dev-dependencies]
tempfile = { workspace = true }
[target.'cfg(target_os = "linux")'.dependencies]
procfs = "0.18"
[target.'cfg(target_os = "windows")'.dependencies]
winapi-util = { workspace = true, optional = true }
windows-sys = { workspace = true, optional = true, default-features = false, features = [

View file

@ -8,16 +8,17 @@
use std::error::Error;
use std::fmt;
#[cfg(target_os = "linux")]
use std::io::BufRead;
use std::num::{IntErrorKind, ParseIntError};
use crate::display::Quotable;
#[cfg(target_os = "linux")]
use procfs::{Current, Meminfo};
/// Error arising from trying to compute system memory.
enum SystemError {
IOError,
ParseError,
#[cfg(not(target_os = "linux"))]
NotFound,
}
@ -43,25 +44,37 @@ impl From<ParseIntError> for SystemError {
/// entry in the file.
#[cfg(target_os = "linux")]
fn total_physical_memory() -> Result<u128, SystemError> {
// On Linux, the `/proc/meminfo` file has a table with information
// about memory usage. For example,
//
// MemTotal: 7811500 kB
// MemFree: 1487876 kB
// MemAvailable: 3857232 kB
// ...
//
// We just need to extract the number of `MemTotal`
let table = std::fs::read("/proc/meminfo")?;
for line in table.lines() {
let line = line?;
if line.starts_with("MemTotal:") && line.ends_with("kB") {
let num_kilobytes: u128 = line[9..line.len() - 2].trim().parse()?;
let num_bytes = 1024 * num_kilobytes;
return Ok(num_bytes);
let info = Meminfo::current().map_err(|_| SystemError::IOError)?;
Ok((info.mem_total as u128).saturating_mul(1024))
}
/// Return the number of bytes of memory that appear to be currently available.
#[cfg(target_os = "linux")]
pub fn available_memory_bytes() -> Option<u128> {
let info = Meminfo::current().ok()?;
if let Some(available_kib) = info.mem_available {
let available_bytes = (available_kib as u128).saturating_mul(1024);
if available_bytes > 0 {
return Some(available_bytes);
}
}
Err(SystemError::NotFound)
let fallback_kib = (info.mem_free as u128)
.saturating_add(info.buffers as u128)
.saturating_add(info.cached as u128);
if fallback_kib > 0 {
Some(fallback_kib.saturating_mul(1024))
} else {
total_physical_memory().ok()
}
}
/// Return `None` when the platform does not expose Linux-like `/proc/meminfo`.
#[cfg(not(target_os = "linux"))]
pub fn available_memory_bytes() -> Option<u128> {
None
}
/// Get the total number of bytes of physical memory.