Rust 通过Tokio UnixStream与子进程通信
我试图让父进程和子进程使用Tokio相互通信。问题是,由于某种原因,孩子无法读取父母写入套接字的任何内容(可能是相反的方式) 我的函数类似于下面的Rust 通过Tokio UnixStream与子进程通信,rust,fork,socketpair,tokio,Rust,Fork,Socketpair,Tokio,我试图让父进程和子进程使用Tokio相互通信。问题是,由于某种原因,孩子无法读取父母写入套接字的任何内容(可能是相反的方式) 我的函数类似于下面的 pub async fn run()->结果{ 让mut socks=UnixStream::pair()?; 火柴叉{ Ok(ForkResult::Parent{..})=>{ 袜子。0。写_u32(31337)。等待?; 好(()) } Ok(ForkResult::Child)=>{ eprintln!(“从大师那里读”); 让msg=soc
pub async fn run()->结果{
让mut socks=UnixStream::pair()?;
火柴叉{
Ok(ForkResult::Parent{..})=>{
袜子。0。写_u32(31337)。等待?;
好(())
}
Ok(ForkResult::Child)=>{
eprintln!(“从大师那里读”);
让msg=socks.1.读_u32().等待?;
eprintln!(“从主控{}读取”,msg);
好(())
}
Err()=>Err(错误),
}
}
套接字不会关闭,否则我在尝试从socks.1
读取时会立即出错。如果我将读取移动到父进程中,它将按预期工作。第一行从master
读取会被打印,但第二行永远不会被调用
我无法更改通信模式,因为我将使用execve
启动另一个二进制文件,该二进制文件将与socketpair
进行通信
知道我这里做错了什么吗?这与从async
函数生成的async
/wait
状态机有关吗?当您调用系统调用时:
子进程是用一个名为fork()的线程创建的
tokio中的默认执行器是线程池执行器。子进程将只获取池中的一个线程,因此无法正常工作
我发现通过将线程池设置为仅包含一个线程,我可以使您的程序正常工作,如下所示:
use tokio::prelude::*;
use tokio::net::UnixStream;
use nix::unistd::{fork, ForkResult};
use nix::sys::wait;
use std::io::Error;
use std::io::ErrorKind;
use wait::wait;
// Limit to 1 thread
#[tokio::main(core_threads = 1)]
async fn main() -> Result<(), Error> {
let mut socks = UnixStream::pair()?;
match fork() {
Ok(ForkResult::Parent { .. }) => {
eprintln!("Writing!");
socks.0.write_u32(31337).await?;
eprintln!("Written!");
wait().unwrap();
Ok(())
}
Ok(ForkResult::Child) => {
eprintln!("Reading from master");
let msg = socks.1.read_u32().await?;
eprintln!("Read from master {}", msg);
Ok(())
}
Err(_) => Err(Error::new(ErrorKind::Other, "oh no!")),
}
}
使用东京:前奏曲:*;
使用tokio::net::UnixStream;
使用nix::unistd::{fork,ForkResult};
使用nix::sys::wait;
使用std::io::Error;
使用std::io::ErrorKind;
使用wait::wait;
//限制为1个线程
#[tokio::main(核心线程=1)]
异步fn main()->结果{
让mut socks=UnixStream::pair()?;
火柴叉{
Ok(ForkResult::Parent{..})=>{
eprintln!(“写作!”);
袜子。0。写_u32(31337)。等待?;
eprintln!(“书面的!”);
等待();
好(())
}
Ok(ForkResult::Child)=>{
eprintln!(“从大师那里读”);
让msg=socks.1.读_u32().等待?;
eprintln!(“从主控{}读取”,msg);
好(())
}
Err()=>Err(Error::new(ErrorKind::Other,“噢,不!”),
}
}
我必须做的另一个更改是,通过调用wait()
,强制父对象等待子对象完成—这也是您可能不希望在真正的异步程序中执行的操作
我读到的大多数建议都是,如果需要从线程程序中分叉,可以在创建任何线程之前进行,也可以在分叉后立即在子程序中调用exec\ve()
(这是您计划要做的)