Libev源码分析02:Libev中的IO监视器

一:代码流程

        在Libev中,启动一个IO监视器,等待该监视器上的事件触发,然后调用该监视器的回调函数。整个的流程是这样的:

        首先调用ev_default_loop初始化struct  ev_loop结构;

        然后调用ev_io_init初始化监视器中的属性,该宏主要就是调用ev_init和ev_io_set;

        然后调用ev_io_start启动该监视器,该函数主要是将监视器添加到loop->anfds结构中,将监视的描述符添加到((loop)->fdchanges)中;

 

        调用ev_run开始等待事件的触发,该函数中:

        首先会调用fd_reify函数,该函数根据((loop)->fdchanges)中记录的描述符,将该描述符上的事件添加到backend所使用的数据结构中,比如select中的fd_set中;

        然后调用time_update更新当前的时间,如果日历时间被人为调整的话,则相应的调整超时事件和周期事件;

        调用backend_poll开始等待事件的发生,如果事件在规定时间内触发的话,则会调用fd_event将触发的监视器记录到loop->pendings中;

        backend的监听函数(select,poll,epoll_wait)返回之后,首先再次调用time_update更新当前的时间,然后调用ev_invoke_pending,依次处理loop->pendings中的监视器,调用该监视器的回调函数。

 

        以上就是Libev中IO监视器的工作流程,下面详细分析各个函数:

 

1:ev_default_loop函数

#if EV_MULTIPLICITY
struct ev_loop *
#else
int
#endif
ev_default_loop (unsigned int flags)
{
    if (!ev_default_loop_ptr)
    {
#if EV_MULTIPLICITY
        struct ev_loop *loop = ev_default_loop_ptr = &default_loop_struct;
#else
        ev_default_loop_ptr = 1;
#endif

        loop_init (loop, flags);

        if (ev_backend (loop))
        {
#if EV_CHILD_ENABLE
            ev_signal_init (&childev, childcb, SIGCHLD);
            ev_set_priority (&childev, EV_MAXPRI);
            ev_signal_start (EV_A_ &childev);
            ev_unref (loop); /* child watcher should not keep loop alive */
#endif
        }
        else
            ev_default_loop_ptr = 0;
    }

    return ev_default_loop_ptr;
}

        EV_MULTIPLICITY宏用来决定是否支持多个loop。系统提供了默认的loop结构default_loop_struct,和指向其的指针ev_default_loop_ptr。

        如果支持多个loop,则default_loop_struct就是一个静态的struct ev_loop类型的结构体,其中包含了各种成员,比如ev_tstamp ev_rt_now;  int  pendingpri;等等。

        ev_default_loop_ptr就是指向struct  ev_loop 类型的指针。

 

        如果不支持多个loop,则上述的struct  ev_loop结构就不复存在,其成员都是以静态变量的形式进行定义,而ev_default_loop_ptr也只是一个int变量,用来表明”loop”是否已经初始化成功。

 

         下面的描述,均以支持多个loop为准。

         在ev_default_loop中,首先是调用loop_init初始化loop中的各种成员:

static void loop_init (struct ev_loop *loop, unsigned int flags)
{
    if (!backend)
    {
        origflags = flags;

#if EV_USE_REALTIME
        if (!have_realtime)
        {
            struct timespec ts;

            if (!clock_gettime (CLOCK_REALTIME, &ts))
                have_realtime = 1;
        }
#endif

#if EV_USE_MONOTONIC
        if (!have_monotonic)
        {
            struct timespec ts;

            if (!clock_gettime (CLOCK_MONOTONIC, &ts))
                have_monotonic = 1;
        }
#endif

        /* pid check not overridable via env */
#ifndef _WIN32
        if (flags & EVFLAG_FORKCHECK)
            curpid = getpid ();
#endif

        if (!(flags & EVFLAG_NOENV) && !enable_secure () && getenv ("LIBEV_FLAGS"))
            flags = atoi (getenv ("LIBEV_FLAGS"));

          ev_rt_now          = ev_time ();
          mn_now             = get_clock ();
          now_floor          = mn_now;
          rtmn_diff          = ev_rt_now - mn_now;
#if EV_FEATURE_API
        invoke_cb          = ev_invoke_pending;
#endif

          io_blocktime       = 0.;
          timeout_blocktime  = 0.;
          backend            = 0;
          backend_fd         = -1;
          sig_pending        = 0;
#if EV_ASYNC_ENABLE
        async_pending      = 0;
#endif
          pipe_write_skipped = 0;
          pipe_write_wanted  = 0;
          evpipe [0]         = -1;
          evpipe [1]         = -1;
#if EV_USE_INOTIFY
        fs_fd              = flags & EVFLAG_NOINOTIFY ? -1 : -2;
#endif
#if EV_USE_SIGNALFD
        sigfd              = flags &
  • 2
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值