linux 在针对文件进行IO读写时,存在几种方式,非阻塞模式,阻塞模式也即非同步,同步模式。两个不同的模式读取数据时,同是read获取,但是返回值可能不一样。
非阻塞模式
此种模式下,需要不停的轮询获取数据,且设置的时间周期需要参考对应设置的时间周期,多次调试才可达到最优。下面分享一下串口非阻塞模式读取的基本流程。
- open
input_fd = open("/dev/ttyS1", O_RDWR | O_NOCTTY | O_NDELAY);
此处使用O_NDELAY来设置非阻塞模式。O_NDELAY 是system V早起版本引入的,后续尽量使用POSIX 规定的O_NONBLOCK,允许多次打开时必须设成非阻塞模式.。
这样产生的结果就是在读取不到数据 或者 写入的缓存区满了 马上会return,而不会阻塞等待。 在读取操作时,读取到文件末尾是返回的是0;读不到数据时也会马上返回,但值是-1 并且设置erron 为EAGAIN。
- fctnl
fctnl 是通过设备文件设置文件属性,此处也是可以设置为非阻塞模式的。
fcntl(input_fd, F_SETFL, FNDELAY);
设置FNDELAY 属性是为了read 时,在没有数据时返回0,实际好像还是-1
- select
while(1){
FD_ZERO(&r_fds);
FD_SET(input_fd, &r_fds);
//set Time Out
//sys.boot_completed
memset(&timeout,0x00,sizeof(timeout));
timeout.tv_sec = 0;
timeout.tv_usec = 3*1000; // 3 ms
ret = ::select(input_fd + 1, &r_fds, NULL, NULL, &timeout);
if(ret == 0)
{
continue;
}
else if(ret < 0)
{
break;
}
else if((ret > 0) && FD_ISSET(input_fd, &r_fds))
{
// read the data bytes