大家好,这篇文章介绍了select机制在节省cpu资源上的用途,和多线程相比,它应用更加简单灵活
对于select / poll 机制的原理,参考大牛的博客 :https://blog.csdn.net/vonzhoufz/article/details/44490675
在这里介绍的是select的一般用法
总的来说机制原理较为复杂 , 但是用户API非常简单 只需要调用select(int nfds, fd_set *readfds, fd_set *writefds,fd_set *exceptfds, struct timeval *timeout)函数
用途 :
监测多个文件,只要有某一个文件可读/可写/异常或超时,即返回
int select(int nfds, fd_set *readfds, fd_set *writefds,fd_set *exceptfds, struct timeval *timeout);
最大文件句柄+1 被监测是否可读的文件 超时时间
被监测是否可写的文件
被监测是否有异常的文件
int nfds :
关于句柄的一些理解和整理 感谢qqID : 过去的都过去了,仅供参考 : 柄就和把手一样,你一拉就可以提起一些东西,句柄你也可以通过它得到一些东西,比如说数据,一般是索引类的东西 ;
比如这里也是一个索引 比如说文件描述符,代表你当前进程打开的文件,你连续打开的文件
这里可以看作文件描述符+1。固定的文件有固定的文件描述符 以此来判断对哪个(那些)文件做出响应
百科 : 文件描述符 :内核(kernel)利用文件描述符(file descriptor)来访问文件。文件描述符是非负整数。打开现存文件或新建文件时,内核会返回一个文件描述符。读写文件也需要使用文件描述符来指定待读写的文件。
fd = open(path, O_CREAT | O_RDONLY, 0644); 即为fd ;
返回值 :
执行成功则返回文件描述词状态已改变的个数,如果返回0代表在描述词状态改变前已超过超时时间,没有返回;当有错误发生时则返回-1
fd_set *readfds :
一旦有输入则返回 一个fd_set是一个固定大小的缓冲区。 执行FD_CLR()或FD_SET(),其值为负值或等于或大于FD_SET-SIZE的值fd将导致未定义的行为。 而且,POSIX要求fd是一个有效的文件描述符。
struct timeval *timeout参数情况:
如果参数超时设为:NULL,则表示选择()没有超时,选择将一直被阻塞,直到某个文件描述符上发生了事件。
0:仅检测描述符集合的状态,然后立即返回,并不等待外部事件的发生。特定的时间值:如果在指定的时间段里没有事件发生,选择将超时返回。
下面的宏提供了处理这三种描述词组的方式:
FD_CLR(inr fd,fd_set* set);用来清除描述词组set中相关fd 的位
FD_ISSET(int fd,fd_set *set);用来测试描述词组set中相关fd 的位是否为真
FD_SET(int fd,fd_set*set);用来设置描述词组set中相关fd的位
FD_ZERO(fd_set *set);用来清除描述词组set的全部位
常见的程序片段如下:
fs_set readset;
FD_ZERO(&readset);
FD_SET(fd,&readset);
select(fd+1,&readset,NULL,NULL,NULL);
if(FD_ISSET(fd,readset){……}
功能源代码:触摸屏的select机制实现输入唤醒
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <stdio.h>
#include <stdlib.h>
#include <sys/time.h>
#include <sys/types.h>
#include <unistd.h>
/**********************************************************************
* 函数名称: main
* 功能描述: select实现低cpu占用操作 触摸屏输入事件监测
* 输入参数: 无
* 输出参数: 无
* 返 回 值: 0 - 成功, 其他值 - 失败
* 修改日期 版本号 修改人 修改内容
* -----------------------------------------------
* 2018/04/17 V1.0 石侃侃 创建
* 存在问题: select(fd+1, &rfds, NULL, NULL, &tv); 目前已经实现碰触触摸屏唤醒 (select返回)
但是无法识别可读可写 (&rfds在第二第三个参数都有效)而且不能判断open打开的txt文本文件
***********************************************************************/
main(void)
{
fd_set rfds;
struct timeval tv;
int retval;
int fd;
fd=open("/dev/input/event0",O_RDONLY); /* 触摸屏设备 */
/* Watch stdin (fd 0) to see when it has input. */
FD_ZERO(&rfds);
FD_SET(fd, &rfds);
/* Wait up to five seconds. */
tv.tv_sec = 5;
tv.tv_usec = 0;
retval = select(fd+1, &rfds, NULL, NULL, &tv);/* 超时或者有输入则返回 */
/* Don't rely on the value of tv now! */
if (retval == -1)
perror("select()");
else if (retval)
{
if(FD_ISSET(fd,&rfds))
{
printf("Data is available now ok.\n");
printf("retval=%d\n",retval);
}
else
{
printf("FD_ISSET error");
}
}
else
printf("No data within five seconds.\n"); /* retval=0 */
return 0;
}