Node事件循环的poll(轮询)阶段的执行机制官方没解释清楚啊(这个阶段也是循环执行的吗)

发布于 2022-09-11 23:33:16 字数 2446 浏览 15 评论 0

当进入到poll阶段,并且没有timers被调用的时候,会发生下面的情况:

(1)如果poll队列不为空:

  • Event Loop 将同步的执行poll queue里的callback(新的I/O事件),直到queue为空或者执行的callback到达上线。

(2)如果poll队列为空:

  • 如果脚本调用了setImmediate(), Event Loop将会结束poll阶段并且进入到check阶段执行setImmediate()的回调。
  • 如果脚本没有setImmediate()调用,Event Loop将会等待回调(新的I/O事件)被添加到队列中,然后立即执行它们。

当进入到poll阶段,并且调用了timers的话,会发生下面的情况:

  • 一旦poll queue是空的话,Event Loop会检查是否timers, 如果有1个或多个timers时间已经到达,Event Loop将会回到timer阶段并执行那些timer的callback(即进入到下一次tick)

轮询超时(poll timeout) 计算规则

开始计算轮询超时(poll timeout)。在为 I/O 阻塞前,事件循环会计算它即将会阻塞多长时间。以下为计算该超时的规则:

  • 如果循环带着UV_RUN_NOWAIT标识执行,那么超时将会是 0 。
  • 如果循环即将停止(uv_stop()已在之前被调用),那么超时将会是 0 。
  • 如果循环内没有激活的句柄和请求,那么超时将会是 0 。
  • 如果循环内有激活的闲置句柄,那么超时将会是 0 。
  • 如果有正在等待被关闭的句柄,那么超时将会是 0 。
  • 如果不符合以上所有,那么该超时将会是循环内所有定时器中最早的一个超时时间,如果没有任何一个激活的定时器,那么超时将会是无限长(infinity)。

这段表述我有以下几个问题
1.Event Loop将会等待回调(新的I/O事件)被添加到队列中,然后立即执行它们
是回来一个事件就会立即执行吗还是回来很多事件然后一起执行?
2.poll阶段也是一个循环吗?
poll队列不为空的然后执行队列到为空了就相当于是循环了一次重新进入poll阶段吗?
但我看官方文档上面也没说执行完了去往何处,是重新跳转到为空的状态吗
3.poll timeout有一种情况是无限长(infinity),也就是说会一直阻塞在poll轮询阶段等待IO的回调,等到IO的回调来了执行了过后怎么跳出去呢?
我感觉只能是开始下次poll循环,没有了句柄timeout设为0,然后才能进入下一个阶段也就是check阶段

这是poll的部分源码

void uv__io_poll(uv_loop_t* loop, int timeout) {
    //...
    //处理观察者队列
    while (!QUEUE_EMPTY(&loop->watcher_queue)) {
        //...
    if (w->events == 0)
      op = UV__EPOLL_CTL_ADD;//新增监听这个事件
    else
      op = UV__EPOLL_CTL_MOD;//修改这个事件
    }
     //...
     //阻塞直到监听的事件来临,前面已经算好timeout以防uv_loop一直阻塞下去
    if (no_epoll_wait != 0 || (sigmask != 0 && no_epoll_pwait == 0)) {
      nfds = uv__epoll_pwait(loop->backend_fd,
                events,
                ARRAY_SIZE(events),
                timeout,
                sigmask);
      if (nfds == -1 && errno == ENOSYS)
        no_epoll_pwait = 1;
    } else {
      nfds = uv__epoll_wait(loop->backend_fd,
               events,
               ARRAY_SIZE(events),
               timeout);
      if (nfds == -1 && errno == ENOSYS)
        no_epoll_wait = 1;
    }
    //...
    for (i = 0; i < nfds; i++) {
        if (w == &loop->signal_io_watcher)
          have_signals = 1;
        else
          w->cb(loop, w, pe->events);//执行callback
    }
    //...
}

我也没看到外层是一个循环啊

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。
列表为空,暂无数据
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文