1、select()函数介绍:
原型:int select(int nfds, fd_set *readfds, fd_set *writefds,fd_set *exceptfds, struct timeval *timeout);
功能:对具有阻塞特性的IO进行监听,若其中有一个或多个IO需要被响应时,系统能快速的回应。解决因一个IO阻塞而影响其他IO要立即被响应的弊端。
参数:
nfds:需要监听最大文件操作符加1
readfds/writefds/exceptfds:分别是被监听的读、写、异常队列
timeout:设置超时的时间,有一个专用的结构体来进行设置。
为什么要这个函数:
譬如:终端要求能回显从键盘输入字符串的同时,还要能显示鼠标输入的东西(可能是乱码)。
如果不用多线程/多进程,那么实现的效果会很差、用户体验也不好。为什么呢?一般会这样构思这段程序:
..........
..........
int main()
{
.........
while(1)
{
read(mouse);
printf(mouse);
read(keyboard);
printf(keyboard);
}
........
}
.........
.......
省略n行代码。。。。。
我们来分析一下上述代码框架:首先读取鼠标的输入,然后输出到键盘;再读取键盘的输入,然后输出到屏幕。看似很完美,但是,假如我们一开始就从键盘输入,终端上会有显示吗?答案是不会的,因为read是阻塞函数,没读到内容就一直在哪里等(坚强到你崩溃~_~)。有了select()函数,剧情就发生了180度的大转弯,叫谁谁都回应你,还随叫随到,哈哈哈~瞬间有了一种舒畅的感觉*~*
此外还需要
2、下面一段代码是实现同时监听鼠标和键盘的程序(仅供加深对函数理解用,没有任何经济效益):
/*************************************************************************
> File Name: select.c
> Author: Pompey Wong
> FUNCTION:
> Created Time: Wed 11 Jul 2018 05:23:29 PM CST
************************************************************************/
#include <stdio.h>
#include <sys/select.h>
#include <sys/time.h>
#include <sys/types.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <stdlib.h>
int main()
{
fd_set fds,fdr; //定义监听队列fds、fdr
int fd = open("/dev/input/mouse1",O_RDONLY); //打开鼠标
if(fd == -1)
{
perror("open mouse");
exit(-1);
}
int maxfd,ret;
char buf[64];
struct timeval tim;
//清零两个监听队列
FD_ZERO(&fds);
FD_ZERO(&fdr);
//将鼠标和键盘加入监听队列
FD_SET(0,&fds); //监听键盘
FD_SET(fd,&fds); //监听鼠标
while(1)
{
//实时更新监听队列,且每次触发后,监听队列都会被改变
fdr = fds;
maxfd = fd + 1;
//设置超时时间
tim.tv_sec = 1;
tim.tv_usec = 0;
//设置监听,仅监听读队列,超时时间为1s
//ret = select(maxfd,&fdr,NULL,NULL,&tim);
ret = select(maxfd,&fdr,NULL,NULL,NULL);
printf("ret = %d\n",ret);
if(ret < 0)
{
perror("select");
exit(-1);
}
else if(ret == 0)
{
printf("timeout\n");
continue;
}
if(FD_ISSET(0,&fdr)) //如果键盘事件被触发
{
read(0,buf,sizeof(buf));
//printf("From keyboard:%s\n",buf);
printf("From keyboard\n");
}
if(FD_ISSET(fd,&fdr)) //鼠标事件被触发
{
read(fd,buf,sizeof(buf));
//printf("From mouse:%s\n",buf);
printf("From mouse\n");
}
}
close(fd);
return 0;
}
该程序,只能在root用户下运行。