*在高并发编程中,多次使用IO复用select函数,本篇就来深入剖析一下其内核源码。。。→_→*
了解poll机制底层原理请戳传送门——IO复用——poll机制内核源代码分析
了解select应用实例请戳传送门——IO复用——select函数应用实例
< – 2017-08-11 23:40 – >
还有一部分代码没贴。。。明天把select这个硬骨头啃下来。。。
< – 2017-08-16 13:32 – >
宿舍没网。。我的流量啊。。因为源代码大部分都在Select.c中。。。所以会有点多。。。看官请直接进sys_select。。。
//linux-2.4.0\fs\Select.c
//提供了6个宏函数,返回要求位图或结果位图中对应的下标元素的值
#define __IN(fds, n) (fds->in + n)
#define __OUT(fds, n) (fds->out + n)
#define __EX(fds, n) (fds->ex + n)
#define __RES_IN(fds, n) (fds->res_in + n)
#define __RES_OUT(fds, n) (fds->res_out + n)
#define __RES_EX(fds, n) (fds->res_ex + n)
//这个元素下标可以同时对应三种位图,所以在一个位图中监听存在就行
#define BITS(fds, n) (*__IN(fds, n)|*__OUT(fds, n)|*__EX(fds, n))
static int max_select_fd(unsigned long n, fd_set_bits *fds)
{
unsigned long *open_fds;
unsigned long set;
int max;
/* handle last in-complete long-word first */
set = ~(~0UL << (n & (__NFDBITS-1)));
n /= __NFDBITS; //将所监听的文件描述符的个数转化为位图的元素下标
open_fds = current->files->open_fds->fds_bits+n;
max = 0; //记录最大的序号
if (set) {
set &= BITS(fds, n);
if (set) {
if (!(set & ~*open_fds))
goto get_max;
return -EBADF;
}
}
while (n) {
open_fds--;
n--;
set = BITS(fds, n); //判断在位图下标位n的元素中是否有要监听的文件描述符
if (!set) //如果位图中下标为n的元素中没有要监听的文件描述符,就继续寻找
continue;
if (set & ~*open_fds)
return -EBADF;
if (max) //这里的最大序号可以理解为一个标志位
continue;
get_max:
do {
max++;
set >>= 1;
} while (set);
max += n * __NFDBITS; //再将位图中的元素序号转化为文件描述符对应的个数
}
return max;
}
#define BIT(i) (1UL << ((i)&(__NFDBITS-1)))
#define MEM(i,m) ((m)+(unsigned)(i)/__NFDBITS)
#define ISSET(i,m) (((i)&*(m)) != 0)</