我在学习rust过程中用到了serialport库来进行串口读写,需求很简单,我创建一个子线程,在子线程中只读;然后,在主线程中写,代码如下: use std::io::{self, Write}; use std::sync::{Arc, RwLock}; use std::thread; use std::time::Duration; use serialport;
fn main() { // 配置串口参数 let port_name = "/dev/ttyUSB0"; // 修改为你的设备路径(Windows: "COM1")
// 打开串口(使用读写锁包装)
let port = serialport::new(port_name, 9600).open()
.expect("Failed to open serial port");
let port = Arc::new(RwLock::new(port));
// 克隆端口到子线程用于读取
let read_port = Arc::clone(&port);
let reader = thread::spawn(move || {
let mut buffer = [0u8; 256];
loop {
// 获取读锁(允许多线程并发读)
let port = read_port.read().unwrap();
match port.read(&mut buffer) {
Ok(bytes_read) => {
if bytes_read > 0 {
let data = &buffer[..bytes_read];
println!("Received: {}", String::from_utf8_lossy(data));
}
}
Err(ref e) if e.kind() == io::ErrorKind::TimedOut => {}
Err(e) => eprintln!("Read error: {}", e),
}
// 读锁在此处自动释放
}
});
// 主线程用于写入
let write_port = Arc::clone(&port);
loop {
// 从标准输入读取数据
print!("Enter message to send (or 'exit' to quit): ");
io::stdout().flush().unwrap();
let mut input = String::new();
io::stdin().read_line(&mut input).unwrap();
// 处理退出命令
if input.trim() == "exit" {
break;
}
// 获取写锁(独占访问)
let mut port = write_port.write().unwrap();
port.write_all(input.as_bytes())
.expect("Failed to write to port");
// 写锁在此处自动释放
}
// 等待读取线程结束
reader.join().unwrap();
}
这是deepseek帮我写然后我修改得到,但是的确表达了我的意愿.但是,这段代码编译不通过:
error[E0277]: dyn SerialPort
cannot be shared between threads safely
--> src/main.rs:18:32
|
18 | let reader = thread::spawn(move || {
| __________________-------------_^
| | |
| | required by a bound introduced by this call
19 | | let mut buffer = [0u8; 256];
20 | | loop {
... |
35 | | });
| |_____^ dyn SerialPort
cannot be shared between threads safely
如果把这里的RwLock换成Mutex,再做对应的差异修改是可以的.但是,不符合我的期望,因为如果用Mutex,意味着读的时候不能写,写的时候不能读,这显然不是我期望的. 看了serialport的文档,SerialPort这个Trait的确只Send,没有Sync,所以按Rust的语法要求这里锁的确是不可少的,但因为全程两个线程一个读一个写,必须是RwLock.
面对这个问题,该如何修改呢?我这个新手又找不到答案了
评论区
写评论我的确把问题复杂化了,我反思了一下,原因在于对"同时只能有对一个绑定的可变借用"的理解上,这里直接生出两个可变的绑定,还就真的互不干扰了
三人行必有我师,互相帮助,加油
谢谢帮忙,我新手,目前还只会从通过文档结合所学习到的语法写这个代码. 这么看的话,我和DeepSeek一样,把问题搞复杂了
这不是项目下有读写的例子。 port clone一下就可以了。 不用自己处理。 fn main() { // Open the first serialport available. let port_name = &serialport::available_ports().expect("No serial port")[0].port_name; let mut port = serialport::new(port_name, 9600) .open() .expect("Failed to open serial port");
}