如何在poll、libev、libuv事件循环中运行libserialport?
问题描述
我正尝试将libserialport库集成到支持poll、libev和libuv的解决方案中。用libev或libuv时,可以轻松从libserialport获取串口文件描述符(fd)并监听,示例代码如下:
uv_poll_init(loop, &poller, serial_port_fd); uv_poll_start(&poller, UV_READABLE /*| UV_PRIORITIZED*/, cb);
但我不知道如何在基于poll的默认循环中实现相同功能,现有主循环示例如下:
while(!interrupted){ interrupted = service_one_loop(); //// 此处需添加poll(serial_port_fd)代码并调用串口回调函数 }
另外想了解是否有其他实现方式,比如下面这种轮询非阻塞读取的写法是否可行:
while(!interrupted){ interrupted = service_one_loop(); read_size = sp_nonblocking_read(machine_port, read_buffer, read_buffer_size); if (read_size >= 0) { cb(); } }
解决方案
方式一:整合poll系统调用到现有循环
你可以把串口fd加入poll监听集合,在循环中先通过poll等待事件,再处理业务逻辑和串口事件:
#include <poll.h> struct pollfd fds[1]; int timeout = 10; // 可根据需求调整超时时间,单位ms,0为非阻塞,负数为永久阻塞 // 初始化poll监听配置 fds[0].fd = serial_port_fd; fds[0].events = POLLIN; // 监听串口可读事件 while(!interrupted){ // 等待事件触发 int ret = poll(fds, 1, timeout); if (ret > 0 && (fds[0].revents & POLLIN)) { // 串口有数据可读,执行回调 cb(); } else if (ret == -1) { // 处理poll错误,比如被信号中断 if (errno != EINTR) { // 这里可以添加错误处理逻辑 break; } } interrupted = service_one_loop(); }
方式二:基于libserialport的非阻塞轮询(你提到的写法优化版)
你给出的轮询写法是可行的,但需要优化细节避免无效回调和CPU空转:
while(!interrupted){ interrupted = service_one_loop(); // 先等待串口就绪,避免频繁调用read浪费CPU int wait_ret = sp_wait(machine_port, 10); // 10ms超时 if (wait_ret == SP_OK) { ssize_t read_size = sp_nonblocking_read(machine_port, read_buffer, read_buffer_size); if (read_size > 0) { // 只有读到有效数据时才调用回调 cb(); } else if (read_size == 0) { // 处理串口连接关闭的情况 } } // wait_ret为SP_ERR_TIMEOUT时直接跳过,当前无数据可读 }
这种方式完全基于libserialport的API实现,不需要直接操作文件描述符,更贴合库的设计逻辑。
内容的提问来源于stack exchange,提问作者amit.user105387
相关产品推荐
相关产品推荐

