linux select机制:
就是相当于监控一个文件句柄,直到文件句柄上有数据了,便可以执行某些操作。或者还有一个超时时间,直到时间到了,便可以执行某些操作。
1.所需的头文件有
/* According to POSIX.1-2001 */
#include <sys/select.h>
/* According to earlier standards */
#include <sys/time.h>
#include <sys/types.h>
#include <unistd.h>
2.所用的函数有
int select(int nfds, fd_set *readfds, fd_set *writefds,
fd_set *exceptfds, struct timeval *timeout);
void FD_CLR(int fd, fd_set *set);
int FD_ISSET(int fd, fd_set *set);
void FD_SET(int fd, fd_set *set);
void FD_ZERO(fd_set *set);
nfds:是一个整数值,是指集合中所有文件描述符的范围,即所有文件描述符的最大值加1
readfds:(可选)指针,指向一组等待可读性检查的套接口。
writefds:(可选)指针,指向一组等待可写性检查的套接口。
exceptfds:(可选)指针,指向一组等待错误检查的套接口。
timeout:select()最多等待时间,对阻塞操作则为NULL。
也就是可以选择等待可读,等待可写,等待错误检查,一般我们用的是等待可读。
3.一个典型的例子:(在串口读数据的时候,需要监听文件句柄有没有数据)
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <termios.h>
#include <errno.h>
#include <string.h>
#define BUFSIZE 512
//初始化串口选项:
void setTermios(struct termios * pNewtio, int uBaudRate)
{
bzero(pNewtio, sizeof(struct termios)); /* clear struct for new port settings */
//8N1
pNewtio->c_cflag = uBaudRate | CS8 | CREAD | CLOCAL;
pNewtio->c_iflag = IGNPAR;
pNewtio->c_oflag = 0;
pNewtio->c_lflag = 0; //non ICANON
}
int main(int argc, char **argv)
{
int fd;
int nread;
char buff[BUFSIZE];
struct termios oldtio,newtio;
struct timeval tv;
char *dev ="/dev/ttyLF1";
fd_set rfds;
if ((fd = open(dev, O_RDWR | O_NOCTTY))<0)
{
printf("err: can't open serial port!\n");
return -1;
}
tcgetattr(fd, &oldtio); /* save current serial port settings */
setTermios(&newtio, B115200);
tcflush(fd, TCIFLUSH);
tcsetattr(fd, TCSANOW, &newtio);
tv.tv_sec=30;
tv.tv_usec=0;
while (1)
{
FD_ZERO(&rfds);
FD_SET(fd, &rfds);
if (select(1+fd, &rfds, NULL, NULL, &tv)>0)
{
printf("wait...\n");
if (FD_ISSET(fd, &rfds))
{
nread=read(fd, buff, BUFSIZE);
printf("readlength=%d\n", nread);
buff[nread]='\0';
printf("buff=%s\n", buff);
usleep(1000);
write(fd, buff, nread);
printf("send data\n");
}
}
}
tcsetattr(fd, TCSANOW, &oldtio);
close(fd);
}
4.关键点 ;
fd_set rfds;
FD_ZERO(&rfds);
FD_SET(fd, &rfds); //其中fd是需要监听的文件句柄
select(1+fd, &rfds, NULL, NULL, &tv)
返回值:成功后,select()返回的值大于0,如果超时在任何有趣的事情发生之前过期,则该值可能为零。出错时返回-1。