Libev源码分析10:libev中poll的用例
在Libev中,使用poll作为backend时,涉及到下面几种数据结构:
int *pollidxs;
int pollidxmax; struct pollfd *polls;
int pollmax;
int pollcnt;
polls就是struct pollfd结构的数组,pollmax是该数组的实际大小,pollcnt表示该数组中,有效结构的个数。也就是监控的描述符个数。
pollidxs是整型数组,以描述符fd为下标,pollidxs[fd]表示该fd对应的struct pollfd结构在polls中的下标。pollidxs[fd]== -1表示该描述符无效。pollidxmax表示pollidxs数组的大小。
增加pollidxs这种结构,主要是为了在取消监控fd时,能够快速定位polls,从而加快取消速度。
因此,上面的结构满足等式:
idx = pollidxs [fd];
polls[idx].fd == fd;
1:poll_init
以poll为backend时,相关的函数和数据结构初始化。代码如下:
backend_mintime = 1e-3;
backend_modify = poll_modify;
backend_poll = poll_poll; pollidxs = 0; pollidxmax = 0;
polls = 0; pollmax = 0; pollcnt = 0;
2:poll_modify
主要设置相关fd的struct pollfd结构,完整代码如下:
static void poll_modify (struct ev_loop *loop, int fd, int oev, int nev)
{
int idx; if (oev == nev)
return;
array_needsize (int, pollidxs, pollidxmax, fd + 1, pollidx_init); idx = pollidxs [fd]; if (idx < 0) /* need to allocate a new pollfd */
{
pollidxs [fd] = idx = pollcnt++;
array_needsize (struct pollfd, polls, pollmax, pollcnt, EMPTY2);
polls [idx].fd = fd;
} assert (polls [idx].fd == fd); if (nev)
polls [idx].events = (nev & EV_READ ? POLLIN : 0) | (nev & EV_WRITE ? POLLOUT : 0);
else /* remove pollfd */
{
pollidxs [fd] = -1;
if (expect_true (idx < --pollcnt))
{
polls [idx] = polls [pollcnt];
pollidxs [polls [idx].fd] = idx;
}
}
}
代码还是比较好理解的,首先取得pollidxs [fd]的值,也就是该fd对应的struct pollfd结构在polls数组中的下标。如果该值为-1,说明该fd是第一次加入监控,相应的设置pollidxs[fd]和polls [idx]。
如果env不为0,则设置struct pollfd结构中的events,如果它为0,表示要去除该fd的监控,首先置pollidxs [fd] = -1表示该fd无效,然后去除相应的struct pollfd结构,首先--pollcnt,如果idx == pollcnt,则直接退出即可,否则,将polls数组中的最后一个元素置换到polls[idx]中,并设置相应的pollidxs元素。
3:poll_poll
主要调用poll函数,等待描述符事件的触发。主要是对触发的描述符和事件调用fd_event。主要代码如下:
res = poll (polls, pollcnt, timeout * 1e3);
if (expect_false (res < 0))
{
...
}
else
for (p = polls; res; ++p)
{
assert (("libev: poll() returned illegal result, broken BSD kernel?", p < polls + pollcnt)); if (expect_false (p->revents)) /* this expect is debatable */
{
--res;
if (expect_false (p->revents & POLLNVAL))
fd_kill (EV_A_ p->fd);
else
fd_event (EV_A_ p->fd, (p->revents & (POLLOUT | POLLERR | POLLHUP) ? EV_WRITE : 0)
| (p->revents & (POLLIN | POLLERR | POLLHUP) ? EV_READ : 0));
}
}
最新文章
- 无脑简单 命令升级git Centos
- Django底层剖析之一次请求到响应的整个流程
- asp.net链接数据库问题,设置收藏本站,设置主页
- linux下命令运行目录上程序前面要加./
- Ubiquitous Religions 分类: POJ 2015-06-16 17:13 11人阅读 评论(0) 收藏
- 10个Laravel4开发者必用扩展包
- wcf使用ssl连接方式设置
- java 集合框架(三)Collection
- vs2012,打开早期版本窗体错误
- scala时间和时间戳互转
- ubuntu下makeinfo安装,其实真正安装的是texinfo包
- FTPService工具类
- RxSwift学习笔记7:buffer/window/map/flatMap/flatMapLatest/flatMapFirst/concatMap/scan/groupBy
- LPC18xx/43xx OTP Controller driver
- HDU 3546
- Servlet各版本web.xml的头文件配置模板
- LevelDB场景分析2--Open
- C# CultureInfo中常用的InvariantCulture
- jQuery中resetForm与clearForm的区别?
- 运行百度语音识别官方iOS demo报错: load offline engine failed: 4001