我正在尝试用 Rust 编写一个程序,将字符串写入命名管道。但是,数据仅在程序退出后才显示在接收端。
这是我的代码:
use termion::event::Key;
use termion::input::TermRead;
use termion::raw::IntoRawMode;
use std::io::Write;
use std::fs::{File, OpenOptions};
fn send_data(file: &mut File, payload: &str) -> Result<(), std::io::Error> {
file.write(payload.as_bytes()).unwrap();
// I tried file.write_all() and file.flush(); same result
Ok(())
}
fn main() {
let mut file = OpenOptions::new()
.write(true)
.open("/tmp/my_named_pipe")
.expect("Failed to open named pipe for writing");
let mut stdout = std::io::stdout().into_raw_mode().unwrap();
stdout.flush().unwrap();
loop {
let key = match std::io::stdin().keys().next() {
Some(Ok(input)) => input,
_ => break,
};
match key { // press x to send data, q to quit
Key::Char('q') => break,
Key::Char('x') => send_data(&mut file, "foobar").unwrap(),
_ => (),
}
}
}
我正在使用
mkfifo /tmp/my_named_pipe
创建一个命名管道,并使用 tail -f /tmp/my_named_pipe
开始收听它。然后,在另一个终端窗口中,我运行我的程序(并按“x”几次)。 'tail -f' 没有显示任何内容。当我退出程序(按“q”)时,所有字符串都会立即显示。
我希望每次按键都会调用
send_data()
,并且每次调用都会立即在 tail -f
侧呈现。如何才能做到这一点?
按照建议,这是我在答案中稍微发展的评论。
问题不在 Rust 这边,而是在
tail -f
那边。
使用 mkfifo /tmp/my_named_pipe
创建管道后,我们可以使用以下命令启动生产者:
( while true; do echo -n X ; sleep 1 ; done ) >/tmp/my_named_pipe
这会每秒向管道中写入一个
X
,不带换行符。
在另一个终端中,尝试使用
tail -f /tmp/my_named_pipe
消耗管道不会显示任何内容,直到生产者停止为止。echo -n X
替换为 echo X
(即我们每次生成一个换行符),在生产者中,这不会改变消费者中的任何内容。tail
在输出任何内容之前等待一行无关;这可能是由于它监视管道的方式(我没有花时间研究源代码)。
但是,尝试使用
cat /tmp/my_named_pipe
消耗管道每秒都会显示 x
,即使没有换行符也是如此。tail
造成的。