9 个稳定版本

1.3.0 2020年2月17日
1.2.2 2018年2月25日
1.2.1 2017年8月18日
1.2.0 2017年5月10日
1.0.1 2016年7月12日

#373 in 操作系统


用于 weechat

MIT 许可证

18KB
261

pipe-channel

Rust 编程语言的基于管道的通道实现

Build Status Crates.io Documentation and examples


lib.rs:

基于管道的通道实现。

这个crate提供了一个与 std::sync::mpsc API 类似的通道实现,基于操作系统级别的管道。管道由底层的操作系统内核进行缓冲。

Sender 和 Receiver 结构体都实现了 AsRawFdFromRawFdIntoRawFd 特性,使得它们可以与 select() 系统调用一起使用,或者在需要文件描述符的其他地方。这允许通道轻松集成到各种事件循环中。

示例

use std::thread;
use pipe_channel::*;

let (mut tx, mut rx) = channel();
let handle = thread::spawn(move || {
    tx.send(35).unwrap();
    tx.send(42).unwrap();
});
assert_eq!(rx.recv().unwrap(), 35);
assert_eq!(rx.recv().unwrap(), 42);
handle.join().unwrap();

所有权

std::sync::mpsc 通道不同,Sender::send()Receiver::recv() 都接受 &mut self。因此,无法共享或克隆 Sender。请使用常规的 Arc<Mutex<Sender<T>>> 代替

use std::thread;
use std::sync::{Arc, Mutex};
use pipe_channel::*;

// Create a shared channel that can be sent along from many threads
// where tx is the sending half (tx for transmission), and rx is the receiving
// half (rx for receiving).
let (tx, mut rx) = channel();
let tx = Arc::new(Mutex::new(tx));
for i in 0..10 {
    let tx = tx.clone();
    thread::spawn(move|| {
        let mut tx = tx.lock().unwrap();
        tx.send(i).unwrap();
    });
}

for _ in 0..10 {
    let j = rx.recv().unwrap();
    assert!(0 <= j && j < 10);
}

多线程和多进程

在较低级别,完全支持从一个进程到另一个进程的管道。这意味着在执行fork()之后,可以使用通道在进程之间发送数据。然而,请注意,所涉及的数据可能包括一些进程本地数据,如引用、指针、文件描述符等。因此,这样使用通道并不安全。

与SIGPIPE的关系

当读取端关闭时,在管道上调用write()会将SIGPIPE信号发送给进程。这意味着当相应的Receiver被丢弃时,会向进程发送SIGPIPE。

在Rust可执行程序中,SIGPIPE默认被忽略。但请确保在您的情况下也是如此。Sender::send()只有在底层系统调用返回EPIPE时才会返回Err。有关更多详细信息,请参阅手册页

性能

与针对最高性能调整过的std::sync::mpsc通道不同,这个实现完全依赖于内核。简单来说,它所做的就是在管道中按字节复制对象。对于正常大小的对象来说,这应该足够快。如果您需要发送一个巨大的对象,考虑将其包装到一个Box中,并发送那个。

操作系统兼容性

这应该适用于任何类UNIX操作系统。

恐慌

系统调用的Resultunwrap处理(除了EPIPE)。因此,如果其中任何一个失败,程序将引发恐慌。虽然这种情况很少见,但并非完全意外(例如,程序可能会耗尽文件描述符)。

依赖关系

~1.5MB
~36K SLoC