Rust 如何强制被阻止读取文件的线程恢复运行?
因为Rust没有以非阻塞方式读取文件的内置功能,所以我必须生成一个线程来读取文件Rust 如何强制被阻止读取文件的线程恢复运行?,rust,blocking,resume,Rust,Blocking,Resume,因为Rust没有以非阻塞方式读取文件的内置功能,所以我必须生成一个线程来读取文件/dev/input/fs0,以获取操纵杆事件。假设操纵杆未使用(无需读取),则读取线程在读取文件时被阻塞 主线程是否有办法强制恢复读取线程的阻塞读取,以便读取线程可以干净地退出 在其他语言中,我只需关闭主线程中的文件。这将迫使阻塞读取恢复。但是我在Rust中没有找到这样做的方法,因为读取需要对文件的可变引用。这个想法是只有在有可用数据时才调用file::read。如果没有可用的数据,我们检查一个标志,看看主线程是否
/dev/input/fs0
,以获取操纵杆事件。假设操纵杆未使用(无需读取),则读取线程在读取文件时被阻塞
主线程是否有办法强制恢复读取线程的阻塞读取,以便读取线程可以干净地退出
在其他语言中,我只需关闭主线程中的文件。这将迫使阻塞读取恢复。但是我在Rust中没有找到这样做的方法,因为读取需要对文件的可变引用。这个想法是只有在有可用数据时才调用
file::read
。如果没有可用的数据,我们检查一个标志,看看主线程是否请求停止。如果没有,请等待并重试
以下是使用板条箱的示例:
mio
对于此用途来说是否太重?@WiSaGaN mio明确表示不处理文件的异步IO。对@Shepmaster OP的良好解读似乎不需要异步IO。非阻塞IO可以通过使用mio
和RawFd
events
@WiSaGaN来实现。你知道这在所有主要平台(Linux、Windows、OS X)上是否都有效吗?@Shepmaster不,只是OP使用的是/dev/input/fs0
,所以至少它不是WindowsP
extern crate nonblock;
use std::fs::File;
use std::sync::{Arc, Mutex};
use std::thread;
use std::time::Duration;
use nonblock::NonBlockingReader;
fn main() {
let f = File::open("/dev/stdin").expect("open failed");
let mut reader = NonBlockingReader::from_fd(f).expect("from_fd failed");
let exit = Arc::new(Mutex::new(false));
let texit = exit.clone();
println!("start reading, type something and enter");
thread::spawn(move || {
let mut buf: Vec<u8> = Vec::new();
while !*texit.lock().unwrap() {
let s = reader.read_available(&mut buf).expect("io error");
if s == 0 {
if reader.is_eof() {
println!("eof");
break;
}
} else {
println!("read {:?}", buf);
buf.clear();
}
thread::sleep(Duration::from_millis(200));
}
println!("stop reading");
});
thread::sleep(Duration::from_secs(5));
println!("closing file");
*exit.lock().unwrap() = true;
thread::sleep(Duration::from_secs(2));
println!("\"stop reading\" was printed before the main exit!");
}
fn read_async<F>(file: File, fun: F) -> thread::JoinHandle<()>
where F: Send + 'static + Fn(&Vec<u8>)
{
let mut reader = NonBlockingReader::from_fd(file).expect("from_fd failed");
let mut buf: Vec<u8> = Vec::new();
thread::spawn(move || {
loop {
let s = reader.read_available(&mut buf).expect("io error");
if s == 0 {
if reader.is_eof() {
break;
}
} else {
fun(&buf);
buf.clear();
}
thread::sleep(Duration::from_millis(100));
}
})
}
extern crate nix;
use std::io::Read;
use std::os::unix::io::AsRawFd;
use std::sync::{Arc, Mutex};
use std::thread;
use std::time::Duration;
use nix::poll;
fn main() {
let mut f = std::fs::File::open("/dev/stdin").expect("open failed");
let mut pfd = poll::PollFd {
fd: f.as_raw_fd(),
events: poll::POLLIN, // is there input data?
revents: poll::EventFlags::empty(),
};
let exit = Arc::new(Mutex::new(false));
let texit = exit.clone();
println!("start reading, type something and enter");
thread::spawn(move || {
let timeout = 100; // millisecs
let mut s = unsafe { std::slice::from_raw_parts_mut(&mut pfd, 1) };
let mut buffer = [0u8; 10];
loop {
if poll::poll(&mut s, timeout).expect("poll failed") != 0 {
let s = f.read(&mut buffer).expect("read failed");
println!("read {:?}", &buffer[..s]);
}
if *texit.lock().unwrap() {
break;
}
}
println!("stop reading");
});
thread::sleep(Duration::from_secs(5));
println!("closing file");
*exit.lock().unwrap() = true;
thread::sleep(Duration::from_secs(2));
println!("\"stop reading\" was printed before the main exit!");
}