//! Global kernel info / tuning miscellaneous stuff //! //! The files in this directory can be used to tune and monitor miscellaneous //! and general things in the operation of the Linux kernel.
use std::cmp; use std::collections::HashSet; use std::str::FromStr;
use bitflags::bitflags;
usecrate::{ProcError, ProcResult};
/// Represents a kernel version, in major.minor.release version. #[derive(Debug, Copy, Clone, Eq, PartialEq, Hash)] pubstruct Version { pub major: u8, pub minor: u8, pub patch: u16,
}
impl Version { pubfn new(major: u8, minor: u8, patch: u16) -> Version {
Version { major, minor, patch }
}
/// Parses a kernel version string, in major.minor.release syntax. /// /// Note that any extra information (stuff after a dash) is ignored. /// /// # Example /// /// ``` /// # use procfs_core::KernelVersion; /// let a = KernelVersion::from_str("3.16.0-6-amd64").unwrap(); /// let b = KernelVersion::new(3, 16, 0); /// assert_eq!(a, b); /// /// ``` #[allow(clippy::should_implement_trait)] pubfn from_str(s: &str) -> Result<Self, &'static str> { let pos = s.find(|c: char| c != '.' && !c.is_ascii_digit()); let kernel = iflet Some(pos) = pos { let (s, _) = s.split_at(pos);
s
} else {
s
}; letmut kernel_split = kernel.split('.');
let major = kernel_split.next().ok_or("Missing major version component")?; let minor = kernel_split.next().ok_or("Missing minor version component")?; let patch = kernel_split.next().ok_or("Missing patch version component")?;
let major = major.parse().map_err(|_| "Failed to parse major version")?; let minor = minor.parse().map_err(|_| "Failed to parse minor version")?; let patch = patch.parse().map_err(|_| "Failed to parse patch version")?;
Ok(Version { major, minor, patch })
}
}
impl FromStr for Version { type Err = &'static str;
/// Parses a kernel version string, in major.minor.release syntax. /// /// Note that any extra information (stuff after a dash) is ignored. /// /// # Example /// /// ``` /// # use procfs_core::KernelVersion; /// let a: KernelVersion = "3.16.0-6-amd64".parse().unwrap(); /// let b = KernelVersion::new(3, 16, 0); /// assert_eq!(a, b); /// /// ``` fn from_str(s: &str) -> Result<Self, Self::Err> {
Version::from_str(s)
}
}
impl cmp::Ord for Version { fn cmp(&self, other: &Self) -> cmp::Ordering { matchself.major.cmp(&other.major) {
cmp::Ordering::Equal => matchself.minor.cmp(&other.minor) {
cmp::Ordering::Equal => self.patch.cmp(&other.patch),
x => x,
},
x => x,
}
}
}
impl cmp::PartialOrd for Version { fn partial_cmp(&self, other: &Self) -> Option<cmp::Ordering> {
Some(self.cmp(other))
}
}
/// Represents a kernel type #[derive(Debug, Clone, Eq, PartialEq)] pubstructType { pub sysname: String,
}
implType { pubfn new(sysname: String) -> Type { Type { sysname }
}
}
impl FromStr forType { type Err = &'static str;
/// Parse a kernel type string /// /// Notice that in Linux source code, it is defined as a single string. fn from_str(s: &str) -> Result<Self, Self::Err> {
Ok(Type::new(s.to_string()))
}
}
/// Represents a kernel build information #[derive(Debug, Clone, Eq, PartialEq)] pubstruct BuildInfo { pub version: String, pub flags: HashSet<String>, /// This field contains any extra data from the /proc/sys/kernel/version file. It generally contains the build date of the kernel, but the format of the date can vary. /// /// A method named `extra_date` is provided which would try to parse some date formats. When the date format is not supported, an error will be returned. It depends on chrono feature. pub extra: String,
}
/// Check if SMP is ON pubfn smp(&self) -> bool { self.flags.contains("SMP")
}
/// Check if PREEMPT is ON pubfn preempt(&self) -> bool { self.flags.contains("PREEMPT")
}
/// Check if PREEMPTRT is ON pubfn preemptrt(&self) -> bool { self.flags.contains("PREEMPTRT")
}
/// Return version number /// /// This would parse number from first digits of version string. For example, #21~1 to 21. pubfn version_number(&self) -> ProcResult<u32> { letmut version_str = String::new(); for c inself.version.chars() { if c.is_ascii_digit() {
version_str.push(c);
} else { break;
}
} let version_number: u32 = version_str.parse().map_err(|_| "Failed to parse version number")?;
Ok(version_number)
}
/// Parse extra field to `DateTime` object /// /// This function may fail as TIMESTAMP can be various formats. #[cfg(feature = "chrono")] pubfn extra_date(&self) -> ProcResult<chrono::DateTime<chrono::Local>> { iflet Ok(dt) =
chrono::DateTime::parse_from_str(&format!("{} +0000", &self.extra), "%a %b %d %H:%M:%S UTC %Y %z")
{ return Ok(dt.with_timezone(&chrono::Local));
} iflet Ok(dt) = chrono::DateTime::parse_from_str(&self.extra, "%a, %d %b %Y %H:%M:%S %z") { return Ok(dt.with_timezone(&chrono::Local));
}
Err(ProcError::Other("Failed to parse extra field to date".to_string()))
}
}
impl FromStr for BuildInfo { type Err = &'static str;
/// Parse a kernel build information string fn from_str(s: &str) -> Result<Self, Self::Err> { letmut version = String::new(); letmut flags: HashSet<String> = HashSet::new(); letmut extra: String = String::new();
for s in &mut splited { if s.chars().all(char::is_uppercase) {
flags.insert(s.to_string());
} else {
extra.push_str(s);
extra.push(' '); break;
}
} let remains: Vec<&str> = splited.collect();
extra.push_str(&remains.join(" "));
Ok(BuildInfo { version, flags, extra })
}
}
#[derive(Debug, PartialEq, Eq, Copy, Clone)] /// Represents the data from `/proc/sys/kernel/sem` pubstruct SemaphoreLimits { /// The maximum semaphores per semaphore set pub semmsl: u64, /// A system-wide limit on the number of semaphores in all semaphore sets pub semmns: u64, /// The maximum number of operations that may be specified in a semop(2) call pub semopm: u64, /// A system-wide limit on the maximum number of semaphore identifiers pub semmni: u64,
}
let semmsl = s.next().ok_or("Missing SEMMSL")?; let semmns = s.next().ok_or("Missing SEMMNS")?; let semopm = s.next().ok_or("Missing SEMOPM")?; let semmni = s.next().ok_or("Missing SEMMNI")?;
let semmsl = semmsl.parse().map_err(|_| "Failed to parse SEMMSL")?; let semmns = semmns.parse().map_err(|_| "Failed to parse SEMMNS")?; let semopm = semopm.parse().map_err(|_| "Failed to parse SEMOPM")?; let semmni = semmni.parse().map_err(|_| "Failed to parse SEMMNI")?;
/// The minimum value that can be written to `/proc/sys/kernel/threads-max` on Linux 4.1 or later pubconst THREADS_MIN: u32 = 20; /// The maximum value that can be written to `/proc/sys/kernel/threads-max` on Linux 4.1 or later pubconst THREADS_MAX: u32 = 0x3fff_ffff;
#[cfg(test)] mod tests { usesuper::*;
#[test] fn test_version() { let a = Version::from_str("3.16.0-6-amd64").unwrap(); let b = Version::new(3, 16, 0);
assert_eq!(a, b);
let a = Version::from_str("3.16.0").unwrap(); let b = Version::new(3, 16, 0);
assert_eq!(a, b);
let a = Version::from_str("3.16.0_1").unwrap(); let b = Version::new(3, 16, 0);
assert_eq!(a, b);
}
#[test] fn test_type() { let a = Type::from_str("Linux").unwrap();
assert_eq!(a.sysname, "Linux");
}
#[test] fn test_build_info() { // For Ubuntu, Manjaro, CentOS and others: let a = BuildInfo::from_str("#1 SMP PREEMPT Thu Sep 30 15:29:01 UTC 2021").unwrap(); letmut flags: HashSet<String> = HashSet::new();
flags.insert("SMP".to_string());
flags.insert("PREEMPT".to_string());
assert_eq!(a.version, "1");
assert_eq!(a.version_number().unwrap(), 1);
assert_eq!(a.flags, flags);
assert!(a.smp());
assert!(a.preempt());
assert!(!a.preemptrt());
assert_eq!(a.extra, "Thu Sep 30 15:29:01 UTC 2021"); #[cfg(feature = "chrono")] let _ = a.extra_date().unwrap();
// For Arch and others: let b = BuildInfo::from_str("#1 SMP PREEMPT Fri, 12 Nov 2021 19:22:10 +0000").unwrap();
assert_eq!(b.version, "1");
assert_eq!(b.version_number().unwrap(), 1);
assert_eq!(b.flags, flags);
assert_eq!(b.extra, "Fri, 12 Nov 2021 19:22:10 +0000");
assert!(b.smp());
assert!(b.preempt());
assert!(!b.preemptrt()); #[cfg(feature = "chrono")] let _ = b.extra_date().unwrap();
// For Debian and others: let c = BuildInfo::from_str("#1 SMP Debian 5.10.46-4 (2021-08-03)").unwrap(); letmut flags: HashSet<String> = HashSet::new();
flags.insert("SMP".to_string());
assert_eq!(c.version, "1");
assert_eq!(c.version_number().unwrap(), 1);
assert_eq!(c.flags, flags);
assert_eq!(c.extra, "Debian 5.10.46-4 (2021-08-03)");
assert!(c.smp());
assert!(!c.preempt());
assert!(!c.preemptrt()); // Skip the date parsing for now
}
#[test] fn test_semaphore_limits() { // Note that the below string has tab characters in it. Make sure to not remove them. let a = SemaphoreLimits::from_str("32000 1024000000 500 32000").unwrap(); let b = SemaphoreLimits {
semmsl: 32_000,
semmns: 1_024_000_000,
semopm: 500,
semmni: 32_000,
};
assert_eq!(a, b);
let a = SemaphoreLimits::from_str("1");
assert!(a.is_err() && a.err().unwrap() == "Missing SEMMNS");
let a = SemaphoreLimits::from_str("1 string 500 3200");
assert!(a.is_err() && a.err().unwrap() == "Failed to parse SEMMNS");
}
}
Messung V0.5 in Prozent
¤ Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.0.15Bemerkung:
(vorverarbeitet am 2026-06-27)
¤
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.