Keyboard shortcuts

Press ← or → to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

std.system

Bounded Linux system-information snapshots, implemented in Plenty over std.fs and std.io. No subprocess, background sampler, native dependency, or global cache is involved.

local() -> Result[Procfs, IoError]
open_procfs(path: &std.path.Path) -> Result[Procfs, IoError]

local() opens /proc. open_procfs opens another procfs mount or a directory of captured files; this also supports deterministic tests. Procfs owns a directory handle and closes it on drop. It resolves reads relative to that handle, following the rooted filesystem API’s no-follow rules.

import std.system
from std.path import from_text
from std.system import SystemError

def main() -> Result[(), IoError | SystemError]:
    # A captured procfs file gives fixed values; std.system.local() reads /proc.
    write_text("loadavg", "0.50 0.25 0.10 2/180 4242\n")?
    source = std.system.open_procfs(&from_text(".")?)?
    load = source.load_average()?
    print(load.one_minute, load.runnable_tasks, load.last_pid)?
    live = std.system.local()?
    print("CPUs found:", live.cpu_count()? > 0)?
    Ok(())
0.5 2 4242
CPUs found: True

Queries

Every method returns Result[T, SystemError]. Calls read fresh data; two calls are not one atomic snapshot. Limits are named optional arguments.

MethodResultSourceDefaults
cpu_count()i64 online logical CPU recordsstatmax_bytes=1048576
memory()Memorymeminfomax_bytes=65536
load_average()LoadAverageloadavgmax_bytes=4096
uptime()Uptimeuptimemax_bytes=4096
block_devices()list[BlockDevice]partitionsmax_bytes=1048576, max_devices=4096
disk_io()list[DiskIo]diskstatsmax_bytes=1048576, max_devices=4096
process_ids()sorted list[u32]numeric directory entriesmax_entries=65536
process(pid: u32)ProcessPID/statusmax_bytes=65536

The generated signature index lists every public record field. For example:

source = std.system.local()?
memory = source.memory(max_bytes=65536)?
print(memory.total_bytes, memory.available_bytes)?

Units and meaning

  • Memory reports total/free physical bytes, optional available physical bytes, and total/free swap bytes. MemAvailable is a kernel estimate; Nothing means the field is unavailable, not zero. Free memory excludes reclaimable caches and is usually not the useful estimate of allocation headroom.
  • LoadAverage has 1-, 5-, and 15-minute load values, runnable/total task counts, and the last created PID. Load is not CPU-utilization percent.
  • Uptime.seconds is elapsed boot time, including suspend according to procfs. idle_cpu_seconds sums idle time over CPUs and can exceed elapsed time.
  • BlockDevice gives major/minor device numbers, a name, and size_bytes. Whole disks and partitions can appear; summing them double-counts storage. /proc/partitions reports 1024-byte blocks, so capacity has that granularity. This is not mounted filesystem capacity or free space.
  • DiskIo gives reads/writes completed, bytes read/written, currently in-flight requests, and busy milliseconds. Sector counts are converted using Linux’s fixed 512-byte accounting unit. These are raw counters, not rates. Counters can reset on reboot/device replacement or wrap; detect resets before computing differences. Whole disks and partitions overlap here too. New trailing diskstats fields are ignored; the modern eleven-counter prefix is required.
  • Process gives PID, parent PID, the kernel-reported name and state code, real UID, thread count, and optional virtual/resident bytes. Name escaping from status is preserved, including literal backslash escapes; it is not a command line or executable path. Missing memory fields, for example on kernel threads, yield Nothing. Resident memory is an approximate kernel counter.

The CPU count is not an affinity/cgroup-aware worker-pool size. Memory, load, uptime and devices describe what the mounted files expose, often the host even in a container. PIDs follow the mount’s PID namespace and permissions. This API does not infer a container’s effective CPU or memory quota.

Limits, failures, and races

max_bytes is a Positive[i64]; i64.MAX traps, as does process with pid 0. Entry and device bounds are NonNegative[i64]. A byte-limited read probes one extra byte to distinguish exact-limit EOF from truncation, since proc files often report size zero. Exceeding any bound returns Limit, never a partial successful result. process_ids counts all visited directory entries toward its bound, including non-PID names. Parsing and result storage allocate fallibly; byte limits bound input size, not exact peak memory.

enum SystemError:
    Io(IoError)
    Stream(std.io.StreamError)
    Allocation(AllocError)
    Limit
    Malformed(str)

I/O errors keep their original cause, including missing and inaccessible files. Allocation errors can also occur inside the existing Io/Stream envelopes. Invalid UTF-8, missing required fields, duplicate selected keys, invalid numbers and unit-conversion overflow return Malformed(field_or_source). Unknown meminfo/status keys are ignored. Numeric conversions never truncate or wrap. Scaling checks the full u64 product and preserves the field-specific Malformed error on overflow; counts and byte-limit probe offsets are bounded by their validated limits rather than saturated.

Enumerating PIDs does not read each process’s status or silently skip failures. Call process(pid) for the records wanted, choosing how to handle disappearance or access denial. It opens the PID directory once before reading status, avoiding mixing files from a reused path; the process may still exit and the read may fail. A returned PID is neither a stable identity nor authority to signal a process.

This first interface has no CPU-utilization sampling, filesystem free-space query, command-line decoding, cgroup accounting, or process control. For children owned by the program, use std.process.

Formats follow the kernel’s procfs documentation, disk I/O accounting, and partitions ABI. See the tutorial.