epoll源码分析---sys_epoll_create()函数
eventpoll的优点就不用说了,网上的资料很多,eventpoll的使用也很广泛,特别是在Web服务器中。因为最近要用到epoll,所以好好地看了一下它的实现,把学到的一些东西做下整理,做个记录。一、sys_epoll_create() 其源码如下:
/* * find_next_zero_bit返回的值的范围是0~(size-1),相当于是bit数组中的索引 * @addr: 位图的地址 * @size: 位图的bit位个数 * @offset: 可以理解为bit数组中的索引,也就是说从这个bit位开始查找 */unsigned long find_next_zero_bit(const unsigned long *addr, unsigned long size, unsigned long offset){ /* * 这里BITOP_WORD用来计算offset对应位图中的unsigned long元素在 * addr数组中的索引,所以p为offset所在的unsigned long元素的地址 */ const unsigned long *p = addr + BITOP_WORD(offset); /* * 相当于是offset - (offset % BITS_PER_LONG),也就是offset所在的unsigned long * 之前所有unsigned long元素的bit位个数 */ unsigned long result = offset & ~(BITS_PER_LONG-1); unsigned long tmp; /* * 如果偏移量大于等于位图的大小,则直接 * 返回size。 */ if (offset >= size) return size; /* * 计算offset所在的unsigned long及其之后所有的unsigned long元素中 * 的bit位个数 */ size -= result; /* * 计算offset对应的unsigned long中占用的bit位所在的位置,这个也可以理解 * 为一个索引。假设计算前offset的值为67,计算后offset的值为3,也就是所在 * unsigned long中的第4个bit位。 */ offset %= BITS_PER_LONG; if (offset) { /* * tmp的值为offset所在的unsigned long的值 */ tmp = *(p++); /* * BITS_PER_LONG - offset计算的offset所在的unsigned long元素中offset所在的 * bit位及其之后的bit位个数。tmp中offset所对应的bit位及其之后的bit位都保留,而将 * tmp中offset所对应的bit位之前的bit位都设置为1. */ tmp |= ~0UL >> (BITS_PER_LONG - offset); /* * 如果size小于BITS_PER_LONG,说明offset在最后一个unsigned long元素。 */ if (size < BITS_PER_LONG) goto found_first; /* * 如果tmp取反后为不为0,则说明tmp中有为0的bit位,因此从 * tmp中查找空闲的bit位。 */ if (~tmp) goto found_middle; /* * 如果offset所对应的bit位所在的unsigned long中没有空闲的bit位, * 开始从其之后得unsigned long元素中查找。计算剩余的bit位个数, * 修改已经查找的bit位个数 */ size -= BITS_PER_LONG; result += BITS_PER_LONG; } /* * 如果size小于BITS_PER_LONG,则退出循环 */ while (size & ~(BITS_PER_LONG-1)) { /* * 将下一个查找的元素存储在tmp中,如果tmp取反后不为0,则说明tmp中有为0的bit位,因此 * 从tmp中查找空闲的bit位。 */ if (~(tmp = *(p++))) goto found_middle; /* * 计算剩余的bit位个数,修改已经查找的bit位个数 */ result += BITS_PER_LONG; size -= BITS_PER_LONG; } /* * 如果全部查找后,仍没有找到空闲的bit位,则直接返回result。 * 此时result的值应该为位图的bit位的个数。 */ if (!size) return result; /* * 如果size不为0,则在剩余的最后的bit位(剩余的个数小于BITS_PER_LONG)中查找。 */ tmp = *p;found_first: /* * 因为剩余的bit位个数有可能小于BITS_PER_LONG,因此需要将unsigned long中 * 不用的bit位置为1,以免干扰后续的查找 */ tmp |= ~0UL << size; /* * 如果所有bit位都为1,则说明没有空余的bit位, * 则返回所有的bit位的个数。 */ if (tmp == ~0UL) /* Are any bits zero? */ return result + size; /* Nope. */found_middle: /* * ffz(tmp)返回的是tmp中第一个为0的bit位的索引 */ return result + ffz(tmp);}