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
- std.process — Gerenciamento de processos
- std.fs — Sistema de arquivos
- std.time — Tempo e timestamps
- std.debug — Depuração e stack traces
- std.log — Sistema de logging