Io 如何处理长时间运行的外部函数调用,如在Rust中阻塞I/O?
编者按:这个问题来自Rust 1.0之前的版本,使用了Rust 1.0代码中不存在的术语和函数。所表达的概念仍然相关 我需要在我的Rust程序中通过POSIX文件描述符读取外部进程提供的数据。文件描述符连接保持了很长的时间(小时),另一端不时地向我传递数据。我需要不断地读取和处理数据流 为此,我编写了一个循环,调用Io 如何处理长时间运行的外部函数调用,如在Rust中阻塞I/O?,io,task,ffi,rust,Io,Task,Ffi,Rust,编者按:这个问题来自Rust 1.0之前的版本,使用了Rust 1.0代码中不存在的术语和函数。所表达的概念仍然相关 我需要在我的Rust程序中通过POSIX文件描述符读取外部进程提供的数据。文件描述符连接保持了很长的时间(小时),另一端不时地向我传递数据。我需要不断地读取和处理数据流 为此,我编写了一个循环,调用libc::read()(readv)来读取数据,并在收到数据时进行处理。因为这会阻塞整个调度程序,所以我正在一个新的调度程序上生成一个任务(task::spawn\u sched(S
libc::read()
(readv
)来读取数据,并在收到数据时进行处理。因为这会阻塞整个调度程序,所以我正在一个新的调度程序上生成一个任务(task::spawn\u sched(SingleThreaded)
)。只要它运行,就可以正常工作,但我找不到一种方法来彻底关闭循环
由于循环大部分时间处于阻塞状态,因此我无法使用端口/通道通知循环退出
我试图通过使用一个失败的链接任务来终止循环任务(在监督下生成循环任务,在其中生成一个链接任务,并在失败之前等待端口上的信号发生)(
使用它来终止循环任务)。它在测试中运行良好,但不会中断libc::read()
(任务在读取完成之前不会失败,并且在某个时间会命中task::yield()
)
通过查看libcore源代码,我学到了很多,但似乎找不到合适的解决方案
SIGTERM
?Rust中似乎还没有类似sigaction()
的东西mozilla/rust/pull/11410
之后可以这样做,另请参阅我的其他问题报告,了解rust zmqerickt/rust zmq/issues/24
,这也取决于此。(很抱歉链接)printf'hello\nthere\nworld'>/tmp/testpipe
kill-s usr1$PID\u进程的\u
目前似乎不可能做到这一点,但仍在努力改进异步I/O:Rust 1.0中现在是否有任何关于非阻塞I/O的更新?这一评论要晚很多,但由于这个问题没有公认的答案,我将其放在这里:自1.0以来,io故事发生了很大的变化。目前,人们非常关注asyn使用mio的c i/o,基于linux和windows的内核库(一时记不起来)。可能很快就会有一些语法级别的功能。更一般地说,如果工作线程有一个工作循环,此循环可以检查关机消息。如果它在i/o上被阻止,我不知道是否可以唤醒它。我想了解更多有关这方面的信息。
use future::Either;
use signal_hook::iterator::Signals;
use std::os::unix::io::FromRawFd;
use tokio::{fs::File, io, prelude::*};
type Result<T> = std::result::Result<T, Box<dyn std::error::Error>>;
fn main() -> Result<()> {
let signals = Signals::new(&[signal_hook::SIGUSR1])?;
let signals = signals.into_async()?;
let input = unsafe { std::fs::File::from_raw_fd(5) };
let input = File::from_std(input);
let lines = io::lines(std::io::BufReader::new(input));
let signals = signals.map(Either::A);
let lines = lines.map(Either::B);
let combined = signals.select(lines);
tokio::run({
combined
.map_err(|e| panic!("Early error: {}", e))
.for_each(|v| match v {
Either::A(signal) => {
println!("Got signal: {:?}", signal);
Err(())
}
Either::B(data) => {
println!("Got data: {:?}", data);
Ok(())
}
})
});
Ok(())
}
[package]
name = "future_example"
version = "0.1.0"
authors = ["An Devloper <an.devloper@example.com>"]
edition = "2018"
[dependencies]
tokio = "0.1.22"
signal-hook = { version = "0.1.9", features = ["tokio-support"] }