关于事件驱动的学习二 select()
2010-06-25 11:35
183 查看
通过前面学习aio的过程,理解select()接口就简单了很多。
select 接口的主要功能是用于检查某个或某组的文件句柄 是否状态改变,譬如是否突然变可读,可写,timeout,或有exception等,如果这种改变(或称event)发生,则返回有状态改变的文件句柄的数量。
整个select的关键是: 如何将文件描述符(file descriptor) 跟一个个event联系起来。
select()的做法是,使用一个特征数fd_set. fd_set的每个位都表示一个fd值。举个例子,fd_set的25位则表示fd=25,fd_set的26位则表示fd=26。这样fd_set有多少位就可以标记多少个文件句柄。void FD_CLR(int fd, fd_set *set); 用以清除某fd对应在fd_set上的对应位
man select上就有个很好的例子,我稍做了修改:
/* According to POSIX.1-2001 */ #include <sys/select.h> /* According to earlier standards */ #include <sys/time.h> #include <sys/types.h> #include <unistd.h> 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); |
整个select的关键是: 如何将文件描述符(file descriptor) 跟一个个event联系起来。
select()的做法是,使用一个特征数fd_set. fd_set的每个位都表示一个fd值。举个例子,fd_set的25位则表示fd=25,fd_set的26位则表示fd=26。这样fd_set有多少位就可以标记多少个文件句柄。void FD_CLR(int fd, fd_set *set); 用以清除某fd对应在fd_set上的对应位
void FD_SET(int fd, fd_set *set); 用于标记fd对应在fd_set上的对应位
void FD_ZERO(fd_set *set); 用于至零
int FD_ISSET(int fd, fd_set *set);用于检查某个fd在fd_set上的对于位是否被标记
在看整个select接口:
int select(int nfds, fd_set *readfds, fd_set *writefds, fd_set *exceptfds, struct timeval *timeout); 参数nfds实际是多余的,用于指定最大的句柄值,当然,如果指定的话,就减少了轮循的长度,减少了系统负担。
譬如本次select调用涉及到的最大的句柄数值是233,则nfds最好设为234.
readfds 这是一个fd_set特征数。传地址是因为select()函数未来要修改此值。如果有两个文件需要检查是否出现readable事件,
那么在这两个fd需要用FD_SET()在readfds上设置自己的特征位。
writefds,exceptfds也是类似的功能,只是用来检测是否有writable事件和exception事件 。
select还有个重大的功能是能够坚持timeout事件。 有3种可能:
timeout=NULL,拥塞,知道有一个fd位被置为1,select函数才返回
timeout=NOT ZERO, 等待固定时间,有一个fd位被置为1或时间耗尽,则函数返回
timeout=zero, 非阻塞,函数检查完每个fd后立即返回。
返回对应位为1的fd的总数目。
注意timeval的结构。
struct timeval{
long tv_sec; /* seconds */
long tv_usec; /* microseconds */
}
man select上就有个很好的例子,我稍做了修改:
#include <stdio.h> #include <sys/time.h> #include <sys/types.h> #include <unistd.h> int main(void) { fd_set rfds; struct timeval tv; int retval; /* Watch stdin (fd 0) to see when it has input. */ FD_ZERO(&rfds); /* 清零 */ FD_SET(, &rfds); /* 为stdin置位 */ /* Wait up to five seconds. */ tv.tv_sec = 5; /*如果5秒内没有event,则退出*/ tv.tv_usec = 0; retval = select(1, &rfds, NULL, NULL, &tv); /* 只需哟扫描掉fd=1即可 */ /* Don't rely on the value of tv now! */ /* 注意select()是阻塞的 */ if (retval == -1) /*返回出错*/ perror("select()"); else if (retval) /*返回说有多少文件接受到event,应该是1个*/ if( FD_ISSET(0, &rfds) ) /*确认STDIN确实能读了*/ printf("Data is available now./n"); else /*阻塞时间超过了5秒,但还是没有event*/ printf("No data within five seconds./n"); return 0; } |
相关文章推荐
- 关于事件驱动学习三 使用select的socket callback模型
- 关于事件驱动的学习三 自己手动写事件驱动
- 关于PHP-Zend framework2 框架 学习过程。 阅前须知: ZF2中的配置文件是可以静态文件配置来注册和通过相关函数动态注册。 1.EventManager(事件驱动),关于事件驱动,在ZF2相关资料没有详细说明,可以参考ANDROID的事件驱动,MFC的消息响应/事件驱动。
- SDL学习(三)事件驱动编程
- 读书整理-关于.net内置事件的驱动原理浅析
- Redis 源码学习之事件驱动
- 关于jquery input textare 事件绑定及用法学习
- 关于如何设计一个基于事件驱动架构的思考
- Python自动化之select、greenlet和gevent和事件驱动模型初探
- muduo网络库学习(八)事件驱动循环线程池EventLoopThreadPool
- [C#]关于事件驱动的SOCKET类的优化
- 关于磁盘驱动的学习 转星际盟主
- ABAP--关于SAP的Control Framework的事件注册的学习
- 关于MSSQL 2000中Select语句FOR XML产生XML文件学习心得
- 关于select 被选中触发事件,onclick事件失效问题
- 学习领域驱动之前的准备——事件驱动
- linux 驱动学习之poll与select
- 关于Android 事件分发机制的学习
- Chap 7 学习笔记-事件驱动编程技术和回送
- Unity插件之NGUI学习(6)—— 关于Widget怎样加入触发事件(触发OnClick)