Zig 如何創建子進程

在 C 裏面,fork/exec 是一套典型的創建新進程的方式,Zig 裏面對此進行的一定封裝,提供了 std.process.Child 結構來簡化這一流程,下面看一示例:

const std = @import("std");
const print = std.debug.print;
const Child = std.process.Child;
const ArrayList = std.ArrayList;
pub fn main() !void {
    var gpa = std.heap.GeneralPurposeAllocator(.{}){};
    defer if (gpa.deinit() != .ok) @panic("leak");
    const allocator = gpa.allocator();
    const argv = [_][]const u8{
        "echo",
        "-n",
        "hello",
        "world",
    };
    // By default, child will inherit stdout & stderr from its parents,
    // this usually means that child's output will be printed to terminal.
    // Here we change them to pipe and collect into `ArrayList`.
    var child = Child.init(&argv, allocator);
    child.stdout_behavior = .Pipe;
    child.stderr_behavior = .Pipe;
    var stdout = ArrayList(u8).init(allocator);
    var stderr = ArrayList(u8).init(allocator);
    defer {
        stdout.deinit();
        stderr.deinit();
    }
    try child.spawn();
    try child.collectOutput(&stdout, &stderr, 1024);
    const term = try child.wait();
    try std.testing.expectEqual(term.Exited, 0);
    try std.testing.expectEqualStrings("hello world", stdout.items);
    try std.testing.expectEqualStrings("", stderr.items);
}

在使用Child.init初始化後,爲了能夠捕獲子進程的標準輸出與錯誤輸出,需要修改 behavior 爲.Pipe,這樣在 spawn 時,Zig 就會給 stdout、stderr 這兩個文件創建兩個管道,之後再調用 collectOutput 這個方法來收集他們就可以了,這個方法內會調用 poll[1] 來對 stdout、stderr 這兩個文件同時監聽讀請求,直到這兩個文件都已經返回 EOF 爲止。

加入我們

Zig 中文社區是一個開放的組織,我們致力於推廣 Zig 在中文羣體中的使用,有多種方式可以參與進來:

  1. 供稿,分享 [2] 自己使用 Zig 的心得

  2. 改進 ZigCC 組織下的開源項目 [3]

  3. 加入微信羣 [4]

參考資料

[1]

poll:https://man7.org/linux/man-pages/man2/poll.2.html

[2]

供稿,分享:https://ziglang.cc/contributing

[3]

開源項目:https://ask.ziglang.cc/github

[4]

微信羣:https://ask.ziglang.cc/weixin

本文由 Readfog 進行 AMP 轉碼,版權歸原作者所有。
來源https://mp.weixin.qq.com/s/1lpQB1_urRE-SJfTZcv-0Q