epoll 监听串口有数据后 read 卡死
时间: 2024-02-11 07:09:37 浏览: 107
监听串口,读出数据
3星 · 编辑精心推荐
类似于在网络编程中使用epoll来监听文件描述符的变化一样,在串口编程中也可以使用epoll来实现监听串口是否有数据可读。但是在读取串口数据时可能会出现卡死的问题,这是因为read函数默认是阻塞的,如果没有数据可读,会一直等待,导致程序卡死。
为了解决这个问题,可以将串口设置为非阻塞模式,这样当没有数据可读时,read函数会立即返回,并返回-1并设置errno为EAGAIN或EWOULDBLOCK。在使用epoll监听串口时,当检测到串口有数据可读时,再使用非阻塞模式的read函数读取数据,如果返回值为-1且errno为EAGAIN或EWOULDBLOCK,则说明当前没有数据可读,程序可以继续执行其他操作。
下面是一个使用epoll监听串口并读取数据的示例代码:
```c
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <fcntl.h>
#include <termios.h>
#include <sys/epoll.h>
#define BUF_SIZE 1024
#define MAX_EVENTS 10
int main(int argc, char *argv[]) {
int fd;
struct termios tty;
struct epoll_event ev, events[MAX_EVENTS];
char buf[BUF_SIZE];
int n, i, nfds, epollfd;
// 打开串口
fd = open("/dev/ttyUSB0", O_RDWR | O_NOCTTY | O_NONBLOCK);
if (fd == -1) {
perror("open");
exit(EXIT_FAILURE);
}
// 设置串口属性
memset(&tty, 0, sizeof(tty));
tty.c_cflag = B9600 | CS8 | CLOCAL | CREAD;
tty.c_iflag = IGNPAR;
tty.c_oflag = 0;
tty.c_lflag = 0;
tcsetattr(fd, TCSANOW, &tty);
// 创建epoll实例
epollfd = epoll_create1(0);
if (epollfd == -1) {
perror("epoll_create1");
exit(EXIT_FAILURE);
}
// 添加串口描述符到epoll实例中
ev.events = EPOLLIN;
ev.data.fd = fd;
if (epoll_ctl(epollfd, EPOLL_CTL_ADD, fd, &ev) == -1) {
perror("epoll_ctl");
exit(EXIT_FAILURE);
}
while (1) {
// 等待文件描述符变化
nfds = epoll_wait(epollfd, events, MAX_EVENTS, -1);
if (nfds == -1) {
perror("epoll_wait");
exit(EXIT_FAILURE);
}
// 处理所有可读事件
for (i = 0; i < nfds; i++) {
if (events[i].events & EPOLLIN) {
// 读取串口数据
n = read(fd, buf, BUF_SIZE);
if (n == -1) {
if (errno == EAGAIN || errno == EWOULDBLOCK) {
// 当前没有数据可读,继续执行其他操作
continue;
} else {
perror("read");
exit(EXIT_FAILURE);
}
} else if (n == 0) {
// 串口已关闭
printf("Serial port closed.\n");
exit(EXIT_SUCCESS);
} else {
// 处理读取到的数据
buf[n] = '\0';
printf("Received data: %s", buf);
}
} else if (events[i].events & (EPOLLHUP | EPOLLERR)) {
// 串口出错或被关闭
printf("Serial port error or closed.\n");
exit(EXIT_FAILURE);
}
}
}
// 关闭串口
close(fd);
return 0;
}
```
在上面的示例代码中,我们使用了非阻塞模式的read函数来读取串口数据,并在epoll事件循环中处理所有可读事件。当没有数据可读时,程序会立即返回并继续执行其他操作,避免了read函数阻塞程序的问题。
阅读全文