5 个版本

0.1.4 2020 年 11 月 15 日
0.1.3 2020 年 10 月 1 日
0.1.2 2020 年 8 月 20 日
0.1.1 2020 年 8 月 11 日
0.1.0 2020 年 8 月 11 日

#306Unix API

Download history 1525/week @ 2024-03-14 2196/week @ 2024-03-21 1666/week @ 2024-03-28 1488/week @ 2024-04-04 1174/week @ 2024-04-11 1260/week @ 2024-04-18 1158/week @ 2024-04-25 1327/week @ 2024-05-02 1389/week @ 2024-05-09 1307/week @ 2024-05-16 1161/week @ 2024-05-23 1158/week @ 2024-05-30 1143/week @ 2024-06-06 1063/week @ 2024-06-13 1171/week @ 2024-06-20 908/week @ 2024-06-27

4,454 每月下载量
用于 4 个 crate (3 个直接)

MIT/Apache

18KB
174

Linux 的进程文件描述符 (pidfd)

进程文件描述符 (pidfd) 提供了一种无竞态条件的方式来管理 Linux 上的进程,通过文件描述符而不是进程 ID (PID) 来维护对进程的持久引用,进程退出后 PID 可能会被重用。

此 crate 仅适用于 Linux;如果您需要支持其他平台或较旧的 Linux 内核,请参阅 async-process

async-pidfd 为 pidfd 提供了 Rust 支持,并支持同步(通过 PidFd 类型)和异步(通过 AsyncPidFd 类型)管理进程。

同步 - PidFd

PidFd 类型用于同步管理进程。使用 PidFd::from_pid 从进程 ID 构造一个 PidFd,例如从标准库中的 Child::id。注意,可移植的 Child::id 函数返回进程 ID 作为 u32,而不是作为 libc::pid_t,需要强制类型转换。

use std::os::unix::process::ExitStatusExt;
use std::process::{Command, ExitStatus};

use async_pidfd::PidFd;

fn main() -> std::io::Result<()> {
    let child = Command::new("/bin/true").spawn()?;
    let pidfd = PidFd::from_pid(child.id() as libc::pid_t)?;
    let status = pidfd.wait()?.status();
    assert_eq!(status.code(), Some(0));

    let child = Command::new("/bin/sh").arg("-c").arg("kill -9 $$").spawn()?;
    let pidfd = PidFd::from_pid(child.id() as libc::pid_t)?;
    let status = pidfd.wait()?.status();
    assert_eq!(status.signal(), Some(9));

    Ok(())
}

PidFd::wait通过ExitInfo结构返回有关已退出进程的信息。ExitInfo包括一个libc::siginfo_t,表示进程如何退出(包括如果正常退出,则为退出代码,如果是被信号杀死,则为信号),以及一个libc::rusage,描述进程及其子进程的资源使用情况。libc::siginfo_t具有复杂的语义;为了获取std::process::ExitStatus,可以在ExitInfo上调用.status()

请注意,虽然打开任意进程的PID可能与该进程的退出发生竞争,但打开尚未等待的子进程的PID是安全的,因为进程ID将在你等待该进程(或阻塞SIGCHLD)之前不会被重用。

如果你只想使用同步的PidFd类型,你可以使用async-pidfdCargo.toml中的default-features = false来删除与异步相关的依赖项。

异步 - AsyncPidFd

AsyncPidFd类型基于Stjepan Glavina的async-iocrate异步管理进程。async-io提供了一个Async包装器,可以轻松地将任何基于文件描述符的同步类型转换为异步类型;生成的异步代码使用epoll同时等待所有文件描述符。

AsyncPidFd包装了一个Async<PidFd>,并提供与PidFd相同的API,但提供了wait函数的异步版本。

use std::os::unix::process::ExitStatusExt;
use std::process::{Command, ExitStatus};

use async_pidfd::AsyncPidFd;
use futures_lite::future;

async fn async_spawn_and_status(cmd: &mut Command) -> std::io::Result<ExitStatus> {
    let child = cmd.spawn()?;
    let pidfd = AsyncPidFd::from_pid(child.id() as libc::pid_t)?;
    Ok(pidfd.wait().await?.status())
}

fn main() -> std::io::Result<()> {
    future::block_on(async {
        let (status1, status2) = future::try_join(
            async_spawn_and_status(&mut Command::new("/bin/true")),
            async_spawn_and_status(&mut Command::new("/bin/false")),
        )
        .await?;
        assert_eq!(status1.code(), Some(0));
        assert_eq!(status2.code(), Some(1));
        Ok(())
    })
}

依赖项

~0–12MB
~97K SLoC