我左看右看,上看下看,一不小心看懂了select→_→现在就让它现出原形~*
int select(int nfds,fd_set *readfds,fd_set *writefds,fd_set *exceptfds,struct timeval *timeout)
1)nfds参数指定被监听的文件描述符的总数。它通常被设置为select监听的所有的文件描述符中的最大值加1。因为文件描述符是从0开始计数的。
2)readfds,writefds和exceptfds参数分别指向可读、可写和异常等事件对应的文件描述符集合。应用程序调用select函数时,通过这3个参数传入自己感兴趣的文件描述符。select调用返回时,内核将修改它们来通知应用程序哪些文件描述符已经就绪。
//因此fd_set实际上是一个具有32个元素的unsigned long类型的数组
typedef struct {
unsigned long fds_bits [__FDSET_LONGS];
} __kernel_fd_set;
typedef __kernel_fd_set fd_set;
fd_set结构体仅包含一个整形数组,该数组的每个元素的每一位标记一个文件描述符。fd_set能容纳的文件描述符数量由FD_SETSIZE指定,这就限制了select能同时处理的文件描述符的总量。
3)timeout参数用来设置select函数的超时时间,如果是0,则select立刻返回。如果是NULL,select将一直阻塞,直到某个文件描述符上有时间发生。
select中重要的数据结构fd_set_bits,poll_table_page,poll_tablle_entry,poll_wqueues。
typedef struct {
unsigned long *in, *out, *ex;//要求
unsigned long *res_in, *res_out, *res_ex;//结果
} fd_set_bits;
struct poll_wqueues {
poll_table pt;
struct poll_table_page * table;
int error;
};
struct poll_table_page {
//一个页面用完了就再分配一个,通过next链成一条单链
struct poll_table_page * next;
//entry总是指向entries中第一个空闲的poll_table_entry结构,根据需要动态的分配entries中的表项
struct poll_table_entry * entry;
//表示该数组可以动态地确定大小,实际使用中分配一个页面,页面中能容纳几个poll_table_entry,这个数组就有多大
struct poll_table_entry entries[0];
};
struct poll_table_entry {
struct file * filp;
wait_queue_t wait;//被封装的wait_queue_t
wait_queue_head_t * wait_address;//等待队列的队头
};
//提供了6个宏函数,返回要求位图或结果位图中对应的下标元素的值
#define __IN(fds, n) (fds->in + n)
#define __OUT(fds, n) (fds->out + n)
#define __EX(fds, n) (fds->ex + n)
#<