菜鸟提问:关于read函数的问题
在linux下用串口接收数据的时候,采用read函数读取串口数据,但是一进入read的循环,程序总是停在那里,跳不出来.不知道为什么.
程序如下:
void readshort(int fd)
{
unsigned int n=5000;
int nread;
char buff[512];
while (n) //循环读取数据
{
printf("start to read data\n");
while((nread = read(fd, buff, 512))>0)
{
// printf("\tLen %d",nread);
buff[nread] = '\0';
printf( "%s", buff);
}
n--;
}
printf("readshort completed");
}
程序执行到这个循环语句的时候,总是跳不出来.是不是我把要读的字节设成512太大了?因为串口那边的数据肯定是小于512的,理论上串口没有数据发过来的时候应该是可以结束读取的呀.
------解决方案--------------------read函数默认是阻塞的.
ioctl(fd, FIONREAD, &status);
if(status>0)
nread = read(fd, buff, status))
或则用select来控制超时.
------解决方案--------------------INT32 ReadComPort (INT32 ComPort, void *data, INT32 datalength)
{
INT32 retval = 0;
static fs_read;
FD_ZERO (&fs_read);
FD_SET (fd[ComPort], &fs_read);
tv_timeout.tv_sec = 0;//TIMEOUT_SEC (datalength, GetBaudrate ());
tv_timeout.tv_usec = 150000;//TIMEOUT_USEC;
retval = select (fd[ComPort] + 1, &fs_read, NULL, NULL, &tv_timeout);
if (retval)
return (read (fd[ComPort], data, datalength));
else
return (-1);
}
------解决方案--------------------tv_timeout.tv_sec:单位是秒
tv_timeout.tv_usec单位是百万分之一秒
合在一起就是表示总的时间
------解决方案--------------------我曾写过一篇文章介绍过select,想了解的话请参考:select函数与I/O多路转接
http://blog.csdn.net/linyt/archive/2007/08/02/1722445.aspx
此外,也可以把它设为非阻塞的,代码如下:
void set_fl(int fd, int flags)
...{
int val;
//获取属性
if((val = fcntl(fd, F_GETFL, 0)) < 0)
...{
printf("get socket property error ");
exit(0);
}
//更改属性
val = val |flags;
//更改属性后再设置,以使它使效
if(fcntl(fd, F_SETFL, val) < 0)
...{
printf("set socket property error ");
exit(1);
}
}
set_fl(fd, O_NONBLOCK);
参见:http://blog.csdn.net/linyt/archive/2007/08/10/1736624.aspx
while((nread = read(fd, buff, 512)) >0)
关于这个代码,如果fd是阻塞的,那么它会阻塞直到有数据来,其中len返回的是数据的个数,小于等于512;并不是要读到512个数据才返回的,只要有数据,那么它就会返回。
如果fd是非阻塞的,如果有数据到数,它会反回读到的数据个数,而没有的时候,它马上返回-1表示没有数据准备好!