我正在嘗試使用生銹的子行程和管道進行練習。練習包括子行程 2 向子行程 1 發送訊息,我在 c1 中收到的訊息必須回傳到 c2,我必須每 2 秒執行 10 次。我有一個代碼可能會這樣做,但是當我想運行它時,它仍在等待,我看不到訊息。
這是我的代碼:
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();
}
謝謝!!!
uj5u.com熱心網友回復:
您可以將資料更改u8為大小為 2 的切片并使用read_exact而不是read_to_string:
Parent { child } => {
drop(reader);
drop(writer_2);
let pid_2 = unsafe{ fork() };
match pid_2.expect("Error creating child 2") {
Parent { child } => {}
Child => {
let mut data: [u8;2] = [0;2];
for _ in 1..10 {
writer.write("C1".as_bytes()).unwrap();
reader_2.read_exact(&mut data).unwrap();
println!("Data from C1, {}", std::str::from_utf8(&data).unwrap());
std::thread::sleep(Duration::from_millis(2000));
}
}
}
}
Child => {
drop(writer);
drop(reader_2);
let mut data: [u8;2] = [0;2];
for _ in 1..10 {
reader.read_exact(&mut data).unwrap();
println!("Data from C2, {}", std::str::from_utf8(&data).unwrap());
writer_2.write(&data).unwrap();
}
}
}
uj5u.com熱心網友回復:
您的代碼等待問題來自 using read_to_string,其中的檔案說(我的重點):
讀取此源中直到 EOF 的所有位元組,并將它們附加到
buf.
第一個孩子通過管道發送一些資料,但沒有關閉它。第二個孩子收到資料,但它想要所有的資料,所以它只是等待對方發送。它只會在收到 EOF 時繼續,但它永遠不會出現,所以你有死鎖。
要修復它,您需要在兩個通信行程之間定義某種協議,以便每一方都可以知道對方何時完成了它的訊息。
在這種情況下,協議可以簡單地“在每條訊息后發送一個換行符”,這樣您read_line就可以輕松實作它。如果資料不是基于文本的,那么您當然需要其他內容。
首先,您需要使用BufReader:
use std::io::BufReader;
然后將兩個閱讀器包裝在一個BufReader:
let mut reader = BufReader::new(reader);
let mut reader_2 = BufReader::new(reader_2);
現在您可以將呼叫交換read_to_string為read_line:
reader.read_line(&mut data).unwrap();
發送資料時,請務必添加換行符,否則會再次死鎖:
writer.write("C1\n".as_bytes()).unwrap();
現在,當接收者收到一條訊息時,它會看到有一個換行符,并將繼續而不等待更多永遠不會到達的位元組。
請注意,read_line回傳包含換行符的行,因此您可能需要將其洗掉。
轉載請註明出處,本文鏈接:https://www.uj5u.com/gongcheng/529288.html
標籤:linuxUnix锈锈货
