Chinaunix首页 | 论坛 | 博客
  • 博客访问: 375653
  • 博文数量: 229
  • 博客积分: 968
  • 博客等级: 准尉
  • 技术积分: 1220
  • 用 户 组: 普通用户
  • 注册时间: 2007-04-07 23:21
文章分类
文章存档

2011年(227)

2010年(2)

分类:

2011-02-24 14:24:34

socket网络编程:IO复用_select函数

摘要:在UNIX系统编程过程中,一个进程往往需要等待多个描述字发生某一事件,如可读、可写或异常等等。进程不能永远地等待其中任何单独一个描述字,它需要同时等待所有描述字,此时就是IO复用技术,系统调用select就是实现这一目标的方式之一。本文详细介绍select函数。

select广泛应用于各种场合,因为select对于任何描述字都有作用,它被应用网络程序,也被应用于终端程序,也被应用其它场合。下面我们先来看看它的函数原型:

#include
#include
int select(int max_fd_p_1, fd_set *readset, fd_set* writeset, fd_set* exceptset, struct timeval* timeout);
返回:就绪描述字的个数,0——超时,-1——出错

select函数有5个参数,我们会介绍每一个参数。

参数max_fd_p_1
内核需要一个数字来指定最大的描述字,因为内核使用这个参数来遍历一组描述字。又因为描述字是从0开始计数的,所以max_fd_p_1实现上是最大描述字的加上1的值。
参数readset
select可以测试一组描述字是否可读,用户需要告诉内核所有关心的描述字,readset就是用来指定关心的描述字集合。
参数writeset
如同readset指定可读描述字集合一样,writeset用来指定关心的可写描述字集合。
参数exceptset
跟readset、writeset一样,exceptset用来指定所关心的异常描述字集合,也就是当集合中一个描述字出现异常时会得到内核的一个通知。
参数timeout
用来指定超时的时长,这是一个结构体:
struct timeval
{
     long tv_sec;//秒数
     long tv_usec;//微秒数
}
这个结体定义在头文件sys/time.h中。

上面我们简单地针对select自身进行了说明。我们注意到,select的参数有4个是指针,如果这些指针取值是空的话会如何?对于指定描述字集合的参数,如果取空的话,它们的意义很直接,就是没有相应的关心的描述字集合。比如readset==NULL,则说明用户不关心任何一个描述字是否可读,对于writeset、exceptset也完全一样。但是对于timeout==NULL的情况就是很直接的,它表示永远等待下去,此时我们不关心需要等待多长时间,我们只要求至少有一个描述字满足用户所关心的。

对于timeout里面两个成员都取值0的时候,相应意义很直接,就是等待0秒0微秒,也就是说不等待任何时间。此时就相当于简单的轮询。

上面我们介绍了最后一个参数的,那么先前的三个参数我需要注意一下,就是它们的类型是fd_set,fd_set是什么样的类型呢?我并不知道,但有一点,就是POSIX标准为我们提供了四个宏,这四个宏可以完成我们需要对fd_set的操作,而fd_set的实际类型留给系统去定义。这四个宏分别是:

void FD_ZERO(fd_set* set);//把set设置为0
void FD_SET(int fd, fd_set* set);//从把fd添加到set
void FD_CLR(int fd, fd_set* set);//从set中删除fd
int FD_ISSET(int fd, fd_set* set);//判断fd是否在set中被设置
使用这四个宏,我们就可以完成fd_set相关的所有操作了。

select是一相十分复杂的函数,它的返回值如上所说,-1为错误,0为超时,正数为就绪的打字个数。但是事实上打字的个数往往很小,系统会一个限制,一般为1024;这是因为fd_set这个类型的限制,同时select也不应该处理过多的打字,否则话会有性能问题。

select也会设置errno值,最常见的值可能就是EINT,表示一个信号中断了select调用,作为应用程序应该在select返回错误的时候查看errno。

阅读(1192) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~