我正在用Rust编写的shell中实现I/O重定向。通过使用带有原始文件描述符和libc crate中的pipe()
的不安全代码,我成功地在两个子进程之间建立了管道。
当我尝试将最后一个子进程的stdout
重定向到我有权限的文件时,它失败了:
extern crate libc;
use std::process::{Command, Stdio};
use std::os::unix::io::{FromRawFd, IntoRawFd};
use std::fs::File;
use self::libc::c_int;
fn main() {
let mut fds = [-1 as c_int, -1 as c_int];
let fd1 = File::open("test1").unwrap().into_raw_fd();
let fd2 = File::open("test2").unwrap().into_raw_fd();
let fd3 = File::open("test3").unwrap().into_raw_fd();
println!("{:?}, {:?}, {:?}", fd1, fd2, fd3);
unsafe {
libc::pipe(&mut fds[0] as *mut c_int);
let cmd1 = Command::new("ls")
.arg("/")
.stdout(Stdio::from_raw_fd(fds[1]))
.spawn()
.unwrap();
let mut cmd2 = Command::new("grep")
.arg("etc")
.stdin(Stdio::from_raw_fd(fds[0]))
.stdout(Stdio::from_raw_fd(fd1))
.spawn()
.unwrap();
let _result = cmd2.wait().unwrap();
}
}
上面那块的结果:
3, 4, 5
grep: write error: Bad file descriptor
看起来文件描述符没有正确返回,但是如果没有名为test1、test 2和test 3的文件,File::open(_).unwrap()
应该会死机,而不是假装打开了一个文件。
如果删除了对文件的重定向,代码工作得很好,即仅使用管道。
2条答案
按热度按时间4smxwvx51#
File::open
的文档说明(重点是我的):尝试以只读模式打开文件。
切换到
File::create
似乎创建了文件,并将“etc”写入其中。此外,您应该:
1.不打开2个额外的文件-没有任何东西关闭这些文件描述符,所以你有一个资源泄漏。
1.检查
pipe
的返回值以处理错误。1.看看nix crate。
bq3bfh9z2#
自从Rust
1.20.0
(在2017-08-31
上发布)以来,您现在可以直接从File
创建Stdio
: