1.select
int select(int nfds, fd_set *readfds, fd_set *writefds,
fd_set *exceptfds, struct timeval *timeout);
功能:select用于监测是哪个或哪些文件描述符产生事件;
有一个或多个同时产生时间返回值。
参数:nfds: 监测的最大文件描述个数
readfds: 读事件集合;
writefds: 写事件集合;
exceptfds:异常事件集合;
timeout:超时检测 1
如果不做超时检测:传 NULL
select返回值:<0 出错
>0 表示有事件产生;
如果设置了超时检测时间:&tv
select返回值:
<0 出错
>0 表示有事件产生;
==0 表示超时时间已到;
struct timeval {
long tv_sec; /* seconds */
long tv_usec; /* microseconds */
};
void FD_CLR(int fd, fd_set *set);//将fd从表中清除
int FD_ISSET(int fd, fd_set *set);//判断fd是否在表中
void FD_SET(int fd, fd_set *set);//将fd添加到表中
void FD_ZERO(fd_set *set);//清空表
select实现IO多路复用特点
1.一个进程最多只能监听1024个文件描述符。
2. select被唤醒之后需要重新轮询一遍驱动的poll函数,效率比较低。
3.select每次会清空表,每次都需要拷贝用户空间的表到内核空间,效率低。
检测鼠标输入事件
#include <stdio.h>
#include <unistd.h>
#include <fcntl.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <sys/select.h>
#include <sys/time.h>
#include <sys/types.h>
#include <unistd.h>
int main(int argc, char const *argv[])
{
//打开鼠标设备
int f = open("/dev/input/mouse0", O_RDONLY);
if (f < 0)
{
perror("open mouse err.");
return -1;
}
//1.创建表
fd_set readfds,tempfds;
FD_ZERO(&readfds);
FD_SET(fd,&readfds);
FD_SET(0,&readfds);
int maxfd=f;
char buf[128];
int ret;
while(1)
{
//3.调用select函数检测事件
tempfds=readfds;
ret=select(maxfd+1,&tempfds,NULL,NULL,NULL);
if(ret < 0)
{
perror("select err.");
return -1;
}
//终端输入
if(FD_ISSET(0,&tempfds))
{
fgets(buf,sizeof(buf),stdin);
printf("key:%s\n",buf);
}
//鼠标输入
if(FD_ISSET(fd,&tempfds))
{
int ret=read(fd,buf,sizeof(buf));
printf("mouse:%s\n",buf);
}
}
close(f);
return 0;
}