std.os em Zig — Referência e Exemplos

std.os — Interface com o Sistema Operacional

O módulo std.os (e seu complemento std.posix) fornece acesso direto às APIs do sistema operacional. No Zig, a filosofia é oferecer wrappers seguros e idiomáticos sobre chamadas de sistema (syscalls) sem esconder a complexidade subjacente. O módulo inclui acesso a variáveis de ambiente, manipulação de sinais, informações do sistema e operações de baixo nível.

Visão Geral

const std = @import("std");
const posix = std.posix;

Na versão atual do Zig, muitas funções que estavam em std.os foram reorganizadas para std.posix (para APIs POSIX) e std.process (para gerenciamento de processos). O std.posix fornece wrappers diretos sobre chamadas de sistema POSIX.

Funções Principais

Variáveis de Ambiente

// Obtém variável de ambiente
pub fn std.posix.getenv(name: []const u8) ?[]const u8

// Via std.process
pub fn std.process.getEnvMap(allocator: Allocator) !EnvMap

Informações do Sistema

// Nome do host
pub fn std.posix.uname() !std.posix.utsname

// ID do processo
pub fn std.posix.getpid() pid_t

// Diretório de trabalho atual
pub fn std.posix.getcwd(buf: []u8) ![]u8

Descritores de Arquivo

// Operações de baixo nível sobre file descriptors
pub fn std.posix.open(path: []const u8, flags: u32, mode: u32) !fd_t
pub fn std.posix.close(fd: fd_t) void
pub fn std.posix.read(fd: fd_t, buf: []u8) !usize
pub fn std.posix.write(fd: fd_t, buf: []const u8) !usize
pub fn std.posix.dup2(oldfd: fd_t, newfd: fd_t) !void

Sinais (Signals)

pub fn std.posix.sigaction(sig: u6, act: *const sigaction, oact: ?*sigaction) void
pub fn std.posix.raise(sig: u8) void

Exemplo 1: Informações do Sistema

const std = @import("std");

pub fn main() !void {
    const stdout = std.io.getStdOut().writer();

    try stdout.writeAll("=== Informações do Sistema ===\n\n");

    // PID do processo
    const pid = std.posix.getpid();
    try stdout.print("PID: {d}\n", .{@as(i32, @bitCast(pid))});

    // Diretório de trabalho atual
    var cwd_buf: [std.fs.max_path_bytes]u8 = undefined;
    const cwd = try std.posix.getcwd(&cwd_buf);
    try stdout.print("CWD: {s}\n", .{cwd});

    // Informações do sistema (uname)
    const info = std.posix.uname();
    try stdout.print("Sistema: {s}\n", .{std.mem.sliceTo(&info.sysname, 0)});
    try stdout.print("Host:    {s}\n", .{std.mem.sliceTo(&info.nodename, 0)});
    try stdout.print("Release: {s}\n", .{std.mem.sliceTo(&info.release, 0)});
    try stdout.print("Arch:    {s}\n", .{std.mem.sliceTo(&info.machine, 0)});

    // Variáveis de ambiente
    try stdout.writeAll("\n=== Variáveis de Ambiente ===\n");

    const vars = [_][]const u8{ "HOME", "USER", "SHELL", "LANG", "PATH" };
    for (vars) |nome| {
        if (std.posix.getenv(nome)) |valor| {
            const preview = if (valor.len > 60) valor[0..60] else valor;
            const suffix = if (valor.len > 60) "..." else "";
            try stdout.print("  {s:<6} = {s}{s}\n", .{ nome, preview, suffix });
        } else {
            try stdout.print("  {s:<6} = (não definida)\n", .{nome});
        }
    }
}

Exemplo 2: Trabalhando com Pipes

const std = @import("std");

pub fn main() !void {
    const stdout = std.io.getStdOut().writer();

    // Cria um pipe
    const pipe_fds = try std.posix.pipe();
    const read_fd = pipe_fds[0];
    const write_fd = pipe_fds[1];

    // Escreve no pipe
    const mensagem = "Mensagem via pipe!";
    _ = try std.posix.write(write_fd, mensagem);
    std.posix.close(write_fd);

    // Lê do pipe
    var buf: [256]u8 = undefined;
    const n = try std.posix.read(read_fd, &buf);
    std.posix.close(read_fd);

    try stdout.print("Recebido via pipe ({d} bytes): {s}\n", .{
        n,
        buf[0..n],
    });
}

Exemplo 3: Monitoramento de Diretório com Timestamps

const std = @import("std");

pub fn main() !void {
    var gpa = std.heap.GeneralPurposeAllocator(.{}){};
    defer _ = gpa.deinit();
    const allocator = gpa.allocator();

    const stdout = std.io.getStdOut().writer();

    // Lista o diretório atual com informações
    var dir = try std.fs.cwd().openDir(".", .{ .iterate = true });
    defer dir.close();

    try stdout.writeAll("=== Conteúdo do Diretório Atual ===\n\n");
    try stdout.print("{s:<30} {s:>10} {s:<6}\n", .{ "Nome", "Tamanho", "Tipo" });
    try stdout.print("{s:->30} {s:->10} {s:->6}\n", .{ "", "", "" });

    var contagem: u32 = 0;
    var tamanho_total: u64 = 0;

    var iter = dir.iterate();
    while (try iter.next()) |entry| {
        const tipo = switch (entry.kind) {
            .file => "ARQ",
            .directory => "DIR",
            .sym_link => "LINK",
            else => "OUTR",
        };

        // Tenta obter tamanho para arquivos
        if (entry.kind == .file) {
            const stat = dir.statFile(entry.name) catch continue;
            try stdout.print("{s:<30} {d:>10} {s:<6}\n", .{
                entry.name, stat.size, tipo,
            });
            tamanho_total += stat.size;
        } else {
            try stdout.print("{s:<30} {s:>10} {s:<6}\n", .{
                entry.name, "-", tipo,
            });
        }

        contagem += 1;
        if (contagem >= 20) {
            try stdout.writeAll("  ... (limitado a 20 entradas)\n");
            break;
        }
    }
    _ = allocator;

    try stdout.print("\nTotal: {d} entradas, {d} bytes em arquivos\n", .{
        contagem, tamanho_total,
    });
}

Módulos Relacionados

Tutoriais e Receitas Relacionados

Continue aprendendo Zig

Explore mais tutoriais e artigos em português para dominar a linguagem Zig.