数据仅在程序退出后写入命名管道

问题描述 投票:0回答:1

我正在尝试用 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 named-pipes
1个回答
0
投票

按照建议,这是我在答案中稍微发展的评论。

问题不在 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
造成的。

© www.soinside.com 2019 - 2024. All rights reserved.