我正在尝试实现一个练习与子进程和管道生 rust 。练习包括在子进程2发送消息到子进程1,我在c1中收到的消息,我必须返回到c2,我必须这样做10次每2秒。我有一个代码,可能会这样做,但当我想运行它,它仍然等待,我不能看到的消息。
这是我的代码:
use nix::sys::wait::wait;
use nix::unistd::ForkResult::{Child, Parent};
use nix::unistd::fork;
use std::io::prelude::*;
use std::time::Duration;
fn main() {
let (mut reader, mut writer) = os_pipe::pipe().unwrap();
let (mut reader_2, mut writer_2) = os_pipe::pipe().unwrap();
let pid = fork();
match pid.expect("Error during creating child") {
Parent { child } => {
drop(reader);
drop(writer_2);
let pid_2 = fork();
match pid_2.expect("Error creating child 2") {
Parent { child } => {}
Child => {
for _ in 1..10 {
writer.write("C1".as_bytes()).unwrap();
let mut data = String::new();
reader_2.read_to_string(&mut data).unwrap();
println!("Data from C1, {}", data);
std::thread::sleep(Duration::from_millis(2000));
}
}
}
}
Child => {
drop(writer);
drop(reader_2);
for _ in 1..10 {
let mut data = String::new();
reader.read_to_string(&mut data).unwrap();
println!("Data from C2, {}", data);
writer_2.write(data.to_string().as_bytes()).unwrap();
}
}
}
wait().unwrap();
}
谢谢!!!
2条答案
按热度按时间axzmvihb1#
代码等待的问题来自于使用
read_to_string
,它的文档说(我强调的是):读取此源中的所有字节,直到EOF,并将它们附加到
buf
。第一个子进程在管道中发送一些数据,但并不关闭它。第二个子进程接收数据,但它想要 * 所有 * 数据,因此它只是等待另一端发送。它只有在收到EOF时才继续,但EOF永远不会到来,所以你有死锁。
要解决这个问题,您需要在两个通信进程之间定义某种协议,以便每一方都可以知道对方何时完成了它的消息。
在这种情况下,协议可以简单地是“在每条消息后发送一个换行符”,这将使您可以使用
read_line
轻松地实现它。首先,您需要使用
BufReader
:然后将两个读卡器封装在
BufReader
中:现在,您可以将对
read_to_string
的呼叫与对read_line
的呼叫交换:发送数据时,请确保添加换行符,否则将再次死锁:
现在,当接收方收到一条消息时,它会看到有一个换行符,并且会继续,而不等待更多永远不会到达的字节。
请注意,
read_line
返回的行 * 包括换行符 *,因此您可能需要删除它。omtl5h9j2#
您可以将数据更改为大小为2的
u8
切片,并使用read_exact
代替read_to_string
: