2017-03-10 23 views
2

私はRustで書かれたシェルでI/Oリダイレクションを実装しています。私は、生のファイル記述子で安全でないコードとlibcのクレートからpipe()を使用して、2つの子プロセス間のパイプ処理に成功しました。私は許可を持っているファイルへの最後の子プロセスのstdoutをリダイレクトしようとすると子プロセスの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、test2、およびtest3という名前のファイルがない場合は、ファイルを開こうとするのではなく、File::open(_).unwrap()がパニックに陥るはずです。

ファイルへのリダイレクトが削除された場合、つまり配管だけが使用されている場合、コードは完全に正常に機能します。

答えて

3

File::open状態(強調鉱山)のドキュメント:読み取り専用モードでファイルを開くために

試み。

File::createに切り替えるとファイルが作成され、 "etc"が書き込まれます。


また、あなたがすべきである:2つの追加ファイルが開けない

  1. - あなたがリソースリークを持っているので、何も今までに、これらのファイル記述子を閉じません。
  2. pipeの戻り値をチェックしてエラーを処理します。
  3. nix crateをご覧ください。
extern crate libc; 
extern crate nix; 

use std::process::{Command, Stdio}; 
use std::os::unix::io::{FromRawFd, IntoRawFd}; 
use std::fs::File; 

use nix::unistd::pipe; 

fn main() { 
    let fds = pipe().unwrap(); 
    let fd1 = File::create("test1").unwrap().into_raw_fd(); 

    let (pipe_in, pipe_out, file_out) = unsafe { 
     (Stdio::from_raw_fd(fds.0), 
     Stdio::from_raw_fd(fds.1), 
     Stdio::from_raw_fd(fd1)) 
    }; 

    Command::new("ls") 
     .arg("/") 
     .stdout(pipe_out) 
     .spawn() 
     .unwrap(); 

    let mut cmd2 = Command::new("grep") 
     .arg("etc") 
     .stdin(pipe_in) 
     .stdout(file_out) 
     .spawn() 
     .unwrap(); 

    cmd2.wait().unwrap(); 
} 
関連する問題