Linux中的select
系统调用是一种I/O多路复用技术,它允许单个进程/线程处理多个I/O操作。select
可以监视多个文件描述符(例如套接字、串口等),并在这些文件描述符中的任何一个准备好进行I/O操作时返回。
文件描述符:在Linux中,一切皆文件,包括串口、套接字等。每个打开的文件都有一个唯一的文件描述符。
I/O多路复用:允许单个进程/线程处理多个I/O操作,提高程序的并发性能。
select
系统调用主要涉及以下参数:
nfds
:文件描述符集合中最大文件描述符加1。readfds
:可读文件描述符集合。writefds
:可写文件描述符集合。exceptfds
:异常条件文件描述符集合。timeout
:等待时间。select
可以高效地处理多个串口的数据读写。select
可以避免为每个连接创建单独的线程或进程。select
处理串口通信#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <fcntl.h>
#include <sys/select.h>
#include <errno.h>
#define SERIAL_PORT "/dev/ttyS0"
#define BUFFER_SIZE 128
int main() {
int fd;
char buffer[BUFFER_SIZE];
fd_set readfs; // 文件描述符集合
struct timeval timeout;
// 打开串口
fd = open(SERIAL_PORT, O_RDWR | O_NOCTTY | O_NDELAY);
if (fd == -1) {
perror("open_port: Unable to open /dev/ttyS0");
return -1;
}
// 设置串口参数(波特率、数据位、停止位、校验等)
// ...
while (1) {
FD_ZERO(&readfs); // 清空文件描述符集合
FD_SET(fd, &readfs); // 将串口文件描述符加入集合
timeout.tv_sec = 5; // 设置超时时间为5秒
timeout.tv_usec = 0;
int ret = select(fd + 1, &readfs, NULL, NULL, &timeout);
if (ret == -1) {
perror("select error");
break;
} else if (ret == 0) {
printf("select timeout\n");
continue;
}
if (FD_ISSET(fd, &readfs)) { // 检查串口是否有数据可读
int len = read(fd, buffer, BUFFER_SIZE);
if (len > 0) {
buffer[len] = '\0';
printf("Received data: %s\n", buffer);
}
}
}
close(fd);
return 0;
}
termios
库正确设置串口参数。select
的超时设置不合理。通过合理使用select
系统调用,可以有效提升串口通信的效率和可靠性。
领取专属 10元无门槛券
手把手带您无忧上云