1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167
//! 特定于 Linux 的 [`std::process`] 模块中的原语扩展。
//!
//! [`std::process`]: crate::process
#![unstable(feature = "linux_pidfd", issue = "82971")]
use crate::io::Result;
use crate::os::unix::io::{AsFd, AsRawFd, BorrowedFd, FromRawFd, IntoRawFd, OwnedFd, RawFd};
use crate::process;
use crate::sealed::Sealed;
#[cfg(not(doc))]
use crate::sys::fd::FileDesc;
use crate::sys_common::{AsInner, AsInnerMut, FromInner, IntoInner};
#[cfg(doc)]
struct FileDesc;
/// 此类型表示引用进程的文件描述符。
///
/// `PidFd` 可以通过设置 [`Command`] 和 [`create_pidfd`] 上的相应选项来获得。随后,可以通过调用 [`pidfd`] 或 [`take_pidfd`] 从 [`Child`] 中检索创建的 pidfd。
///
/// Example:
///
/// ```no_run
/// #![feature(linux_pidfd)]
/// use std::os::linux::process::{CommandExt, ChildExt};
/// use std::process::Command;
///
/// let mut child = Command::new("echo")
/// .create_pidfd(true)
/// .spawn()
/// .expect("Failed to spawn child");
///
/// let pidfd = child
/// .take_pidfd()
/// .expect("Failed to retrieve pidfd");
///
/// // 当 `pidfd` 关闭时,文件描述符将被关闭。
/// ```
///
/// 有关详细信息,请参见 [`pidfd_open(2)`] 的手册页。
///
/// [`Command`]: process::Command
/// [`create_pidfd`]: CommandExt::create_pidfd
/// [`Child`]: process::Child
/// [`pidfd`]: fn@ChildExt::pidfd
/// [`take_pidfd`]: ChildExt::take_pidfd
/// [`pidfd_open(2)`]: https://man7.org/linux/man-pages/man2/pidfd_open.2.html
#[derive(Debug)]
pub struct PidFd {
inner: FileDesc,
}
impl AsInner<FileDesc> for PidFd {
#[inline]
fn as_inner(&self) -> &FileDesc {
&self.inner
}
}
impl FromInner<FileDesc> for PidFd {
fn from_inner(inner: FileDesc) -> PidFd {
PidFd { inner }
}
}
impl IntoInner<FileDesc> for PidFd {
fn into_inner(self) -> FileDesc {
self.inner
}
}
impl AsRawFd for PidFd {
#[inline]
fn as_raw_fd(&self) -> RawFd {
self.as_inner().as_raw_fd()
}
}
impl FromRawFd for PidFd {
unsafe fn from_raw_fd(fd: RawFd) -> Self {
Self::from_inner(FileDesc::from_raw_fd(fd))
}
}
impl IntoRawFd for PidFd {
fn into_raw_fd(self) -> RawFd {
self.into_inner().into_raw_fd()
}
}
impl AsFd for PidFd {
fn as_fd(&self) -> BorrowedFd<'_> {
self.as_inner().as_fd()
}
}
impl From<OwnedFd> for PidFd {
fn from(fd: OwnedFd) -> Self {
Self::from_inner(FileDesc::from_inner(fd))
}
}
impl From<PidFd> for OwnedFd {
fn from(pid_fd: PidFd) -> Self {
pid_fd.into_inner().into_inner()
}
}
/// 特定于操作系统的 [`Child`] 的扩展
///
/// [`Child`]: process::Child
pub trait ChildExt: Sealed {
/// 获取对为此 [`Child`] 创建的 [`PidFd`] 的引用 (如果可用)。
///
/// 只有在创建相应的 [`Command`] 时使用 [`create_pidfd`] 请求创建 pidfd 时,pidfd 才可用。
///
///
/// 即使请求,pidfd 也可能不可用,因为正在使用旧版本的 Linux,或者如果发生了一些其他错误。
///
/// [`Command`]: process::Command
/// [`create_pidfd`]: CommandExt::create_pidfd
/// [`Child`]: process::Child
///
fn pidfd(&self) -> Result<&PidFd>;
/// 拥有为此 [`Child`] 创建的 [`PidFd`] (如果可用) 的所有权。
///
/// 只有在创建相应的 [`Command`] 时使用 [`create_pidfd`] 请求创建 pidfd 时,pidfd 才可用。
///
///
/// 即使请求,pidfd 也可能不可用,因为正在使用旧版本的 Linux,或者如果发生了一些其他错误。
///
/// [`Command`]: process::Command
/// [`create_pidfd`]: CommandExt::create_pidfd
/// [`Child`]: process::Child
///
fn take_pidfd(&mut self) -> Result<PidFd>;
}
/// 特定于操作系统的 [`Command`] 的扩展
///
/// [`Command`]: process::Command
pub trait CommandExt: Sealed {
/// 设置是否应为此 [`Command`] 生成的 [`Child`] 创建 [`PidFd`](struct@PidFd)。
///
/// 默认情况下,不会创建 pidfd。
///
/// 可以使用 [`pidfd`] 或 [`take_pidfd`] 从子节点那里检索 pidfd。
///
/// pidfd 只会在有可能以保证无竞争的方式 (例如
/// 如果支持 `clone3` 系统调用)。
/// 否则,[`pidfd`] 将返回错误。
///
/// [`Command`]: process::Command
/// [`Child`]: process::Child
/// [`pidfd`]: fn@ChildExt::pidfd
/// [`take_pidfd`]: ChildExt::take_pidfd
fn create_pidfd(&mut self, val: bool) -> &mut process::Command;
}
impl CommandExt for process::Command {
fn create_pidfd(&mut self, val: bool) -> &mut process::Command {
self.as_inner_mut().create_pidfd(val);
self
}
}