Skip to content

Ch 27: std::process - 子进程管理

std::process模块提供了进程管理的完整功能,包括子进程的创建、等待、管道通信和终止。

从Command::spawn返回的Child结构体:

use std::process::{Command, Stdio};
use std::io::{Read, Write};
fn main() {
let mut child = Command::new("cat")
.stdin(Stdio::piped())
.stdout(Stdio::piped())
.spawn()
.expect("启动进程失败");
// 获取子进程的stdin
if let Some(ref mut stdin) = child.stdin {
stdin.write_all(b"Hello from parent!").unwrap();
}
// 获取子进程的stdout
if let Some(ref mut stdout) = child.stdout {
let mut buffer = String::new();
stdout.read_to_string(&mut buffer).unwrap();
println!("子进程输出: {}", buffer);
}
}
pub enum Stdio {
Inherited, // 继承父进程的标准流
Piped, // 创建管道
Null, // 重定向到/dev/null
FromRaw(FileDesc), // 从原始文件描述符创建
}

创建带管道的子进程:

use std::process::{Command, Stdio};
fn main() {
// 创建双向管道
let mut child = Command::new("python3")
.stdin(Stdio::piped())
.stdout(Stdio::piped())
.stderr(Stdio::piped())
.spawn()
.expect("启动失败");
}
use std::process::Command;
fn main() {
let mut child = Command::new("sleep")
.arg("2")
.spawn()
.expect("启动失败");
println!("等待子进程结束...");
// 阻塞等待
let status = child.wait().expect("等待失败");
println!("进程退出状态: {}", status);
println!("是否成功: {}", status.success());
println!("退出码: {:?}", status.code());
}

方法签名:

impl Child {
pub fn wait(&mut self) -> Result<ExitStatus>
pub fn try_wait(&mut self) -> Result<Option<ExitStatus>>
}

try_wait()非阻塞地检查进程状态:

use std::process::Command;
use std::time::Duration;
fn main() {
let mut child = Command::new("sleep")
.arg("10")
.spawn()
.expect("启动失败");
// 非阻塞检查
loop {
match child.try_wait().expect("检查失败") {
Some(status) => {
println!("进程已结束: {}", status);
break;
}
None => {
println!("进程仍在运行...");
std::thread::sleep(Duration::from_secs(1));
}
}
}
}
use std::process::{Command, Stdio};
use std::time::Duration;
fn main() {
let mut child = Command::new("sleep")
.arg("100")
.stdout(Stdio::null())
.spawn()
.expect("启动失败");
println!("子进程PID: {}", child.id());
// 等待一小段时间
std::thread::sleep(Duration::from_secs(1));
// 终止进程
child.kill().expect("终止失败");
// 获取退出状态
let status = child.wait().expect("等待失败");
println!("进程被终止,状态: {}", status);
}

方法签名:

impl Child {
pub fn kill(&mut self) -> Result<()>
}

父子进程通过管道通信:

use std::process::{Command, Stdio};
use std::io::Read;
fn main() {
// 创建管道
let mut child = Command::new("wc")
.arg("-w")
.stdin(Stdio::piped())
.stdout(Stdio::piped())
.spawn()
.expect("启动失败");
// 写入数据
let text = "hello world from rust process";
if let Some(ref mut stdin) = child.stdin {
use std::io::Write;
stdin.write_all(text.as_bytes()).unwrap();
}
// 读取结果
let mut output = String::new();
if let Some(ref mut stdout) = child.stdout {
stdout.read_to_string(&mut output).unwrap();
}
println!("字数统计: {}", output.trim());
}

8. wait_with_output - 等待并获取所有输出

Section titled “8. wait_with_output - 等待并获取所有输出”

便捷方法,一步完成等待和输出获取:

use std::process::Command;
fn main() {
let output = Command::new("ls")
.arg("-la")
.output()
.expect("执行失败");
// output包含stdout、stderr和status
println!("退出码: {:?}", output.status.code());
println!("stdout: {}", String::from_utf8_lossy(&output.stdout));
}
use std::process::{Command, ExitStatus};
fn main() {
let output = Command::new("ls")
.arg("/tmp")
.output()
.expect("执行失败");
let status = output.status;
// 检查退出状态
if status.success() {
println!("命令执行成功");
}
// 获取退出码
if let Some(code) = status.code() {
println!("退出码: {}", code);
}
}

Unix特定方法:

impl ExitStatus {
pub fn signal(&self) -> Option<i32>
pub fn core_dumped(&self) -> bool
pub fn stopped(&self) -> Option<i32>
}
  1. 僵尸进程:必须调用wait()回收子进程资源
  2. 管道缓冲:管道有缓冲区限制,避免写入过多数据
  3. 死锁风险:同时读写父子进程时注意避免循环依赖
  4. 信号处理:子进程可能因信号被终止
  5. 资源清理:Child被drop时会自动wait(如果还没wait)

std::process提供了完整的进程管理能力:

  • Child - 子进程句柄,管理stdin/stdout/stderr
  • Stdio - 标准流配置(继承/管道/null)
  • wait() / try_wait() - 等待进程结束
  • kill() - 终止进程
  • ExitStatus - 退出状态检查

这些API是Rust实现进程间通信(IPC)的基础。