青青草原综合久久大伊人导航_色综合久久天天综合_日日噜噜夜夜狠狠久久丁香五月_热久久这里只有精品

Just enjoy programming

Nginx源碼分析-Epoll模塊(轉(zhuǎn)載)

轉(zhuǎn)載自:http://www.tbdata.org/archives/1296


Nginx源碼分析-Epoll模塊

3 comments 十二月 26th, 2010 | by yixiao in 高性能服務(wù)器

Linux平臺上,Nginx使用epoll完成事件驅(qū)動,實現(xiàn)高并發(fā);本文將不對epoll本身進行介紹(網(wǎng)上一堆一堆的文章介紹epoll的原理及使用方法,甚至源碼分析等),僅看一下Nginx是如何使用epoll的。

Nginx在epoll模塊中定義了好幾個函數(shù),這些函數(shù)基本都是作為回調(diào)注冊到事件抽象層的對應接口上,從而實現(xiàn)了事件驅(qū)動的具體化,我們看如下的一段代碼:

ngx_event_module_t  ngx_epoll_module_ctx = {
    &epoll_name,
    ngx_epoll_create_conf,               /* create configuration */
    ngx_epoll_init_conf,                 /* init configuration */
    {
        ngx_epoll_add_event,             /* add an event */
        ngx_epoll_del_event,             /* delete an event */
        ngx_epoll_add_event,             /* enable an event */
        ngx_epoll_del_event,             /* disable an event */
        ngx_epoll_add_connection,        /* add an connection */
        ngx_epoll_del_connection,        /* delete an connection */
        NULL,                            /* process the changes */
        ngx_epoll_process_events,        /* process the events */
        ngx_epoll_init,                  /* init the events */
        ngx_epoll_done,                  /* done the events */
    }
};


這段代碼就是epoll的相關(guān)函數(shù)注冊到事件抽象層,這里所謂的事件抽象層在前面的博文中有提過,就是Nginx為了方便支持和開發(fā)具體的I/O模型,從而實現(xiàn)的一層抽象。代碼后面的注釋將功能說明得很詳細了,本文就只重點關(guān)注ngx_epoll_init和ngx_epoll_process_events兩個函數(shù),其他幾個函數(shù)就暫且忽略了。

ngx_epoll_init主要是完成epoll的相關(guān)初始化工作,代碼分析如下:

static ngx_int_t
ngx_epoll_init(ngx_cycle_t *cycle, ngx_msec_t timer)
{
    ngx_epoll_conf_t  *epcf;
	/*取得epoll模塊的配置結(jié)構(gòu)*/
    epcf = ngx_event_get_conf(cycle->conf_ctx, ngx_epoll_module);
	/*ep是epoll模塊定義的一個全局變量,初始化為-1*/
    if (ep == -1) {
    	/*創(chuàng)一個epoll對象,容量為總連接數(shù)的一半*/
        ep = epoll_create(cycle->connection_n / 2);
        if (ep == -1) {
            ngx_log_error(NGX_LOG_EMERG, cycle->log, ngx_errno,
                          "epoll_create() failed");
            return NGX_ERROR;
        }
    }
	/*nevents也是epoll模塊定義的一個全局變量,初始化為0*/
    if (nevents events) {
        if (event_list) {
            ngx_free(event_list);
        }

		/*event_list存儲產(chǎn)生事件的數(shù)組*/
        event_list = ngx_alloc(sizeof(struct epoll_event) * epcf->events,
                               cycle->log);
        if (event_list == NULL) {
            return NGX_ERROR;
        }
    }
    nevents = epcf->events;
	/*初始化全局變量ngx_io, ngx_os_is定義為:
		ngx_os_io_t ngx_os_io = {
    		ngx_unix_recv,
    		ngx_readv_chain,
    		ngx_udp_unix_recv,
    		ngx_unix_send,
    		ngx_writev_chain,
    		0
		};(位于src/os/unix/ngx_posix_init.c)
	*/
    ngx_io = ngx_os_io;
	/*這里就是將epoll的具體接口函數(shù)注冊到事件抽象層接口ngx_event_actions上。
	具體是上文提到的ngx_epoll_module_ctx中封裝的如下幾個函數(shù)
        ngx_epoll_add_event,
        ngx_epoll_del_event,
        ngx_epoll_add_event,
        ngx_epoll_del_event,
        ngx_epoll_add_connection,
        ngx_epoll_del_connection,
        ngx_epoll_process_events,
        ngx_epoll_init,
        ngx_epoll_done,
	*/
    ngx_event_actions = ngx_epoll_module_ctx.actions;
#if (NGX_HAVE_CLEAR_EVENT)
	/*epoll將添加這個標志,主要為了實現(xiàn)邊緣觸發(fā)*/
    ngx_event_flags = NGX_USE_CLEAR_EVENT
#else
	/*水平觸發(fā)*/
    ngx_event_flags = NGX_USE_LEVEL_EVENT
#endif
                      |NGX_USE_GREEDY_EVENT /*io的時候,直到EAGAIN為止*/
                      |NGX_USE_EPOLL_EVENT; /*epoll標志*/
    return NGX_OK;
}

epoll初始化工作沒有想象中的復雜,和我們平時使用epoll都一樣,下面看ngx_epoll_process_events,這個函數(shù)主要用來完成事件的等待并處理。

static ngx_int_t
ngx_epoll_process_events(ngx_cycle_t *cycle, ngx_msec_t timer, ngx_uint_t flags)
{
    int                events;
    uint32_t           revents;
    ngx_int_t          instance, i;
    ngx_uint_t         level;
    ngx_err_t          err;
    ngx_log_t         *log;
    ngx_event_t       *rev, *wev, **queue;
    ngx_connection_t  *c;
	/*一開始就是等待事件,最長等待時間為timer;nginx為事件
	專門用紅黑樹維護了一個計時器。后續(xù)對這個timer單獨分析。
	*/
    events = epoll_wait(ep, event_list, (int) nevents, timer);
    if (events == -1) {
        err = ngx_errno;
    } else {
        err = 0;
    }
    if (flags & NGX_UPDATE_TIME || ngx_event_timer_alarm) {
        /*執(zhí)行一次時間更新, nginx將時間緩存到了一組全局變量中,方便程序高效的獲取事件。*/
        ngx_time_update();
    }
	/*處理wait錯誤*/
    if (err) {
        if (err == NGX_EINTR) {
            if (ngx_event_timer_alarm) {
                ngx_event_timer_alarm = 0;
                return NGX_OK;
            }
            level = NGX_LOG_INFO;
        } else {
            level = NGX_LOG_ALERT;
        }
        ngx_log_error(level, cycle->log, err, "epoll_wait() failed");
        return NGX_ERROR;
    }
	/*wait返回事件數(shù)0,可能是timeout返回,也可能是非timeout返回;非timeout返回則是error*/
    if (events == 0) {
        if (timer != NGX_TIMER_INFINITE) {
            return NGX_OK;
        }
        ngx_log_error(NGX_LOG_ALERT, cycle->log, 0,
                      "epoll_wait() returned no events without timeout");
        return NGX_ERROR;
    }
    log = cycle->log;
	/*for循環(huán)開始處理收到的所有事件*/
    for (i = 0; i read;
		。。。。。。。。。。。。。

		/*取得發(fā)生一個事件*/
        revents = event_list[i].events;

		/*記錄wait的錯誤返回狀態(tài)*/
        if (revents & (EPOLLERR|EPOLLHUP)) {
            ngx_log_debug2(NGX_LOG_DEBUG_EVENT, log, 0,
                           "epoll_wait() error on fd:%d ev:%04XD",
                           c->fd, revents);
        }
        if ((revents & (EPOLLERR|EPOLLHUP))
             && (revents & (EPOLLIN|EPOLLOUT)) == 0)
        {
            /*
             * if the error events were returned without EPOLLIN or EPOLLOUT,
             * then add these flags to handle the events at least in one
             * active handler
             */
            revents |= EPOLLIN|EPOLLOUT;
        }
		/*該事件是一個讀事件,并該連接上注冊的讀事件是active的*/
        if ((revents & EPOLLIN) && rev->active) {
            if ((flags & NGX_POST_THREAD_EVENTS) && !rev->accept) {
                rev->posted_ready = 1;
            } else {
                rev->ready = 1;
            }

			/*事件放入相應的隊列中;關(guān)于此處的先入隊再處理,在前面的文章中已經(jīng)介紹過了。*/
            if (flags & NGX_POST_EVENTS) {
                queue = (ngx_event_t **) (rev->accept ?
                               &ngx_posted_accept_events : &ngx_posted_events);
                ngx_locked_post_event(rev, queue); /*入隊*/
            } else {
                rev->handler(rev);
            }
        }
        wev = c->write;
		/*發(fā)生的是一個寫事件,和讀事件完全一樣的邏輯過程*/
        if ((revents & EPOLLOUT) && wev->active) {
            if (flags & NGX_POST_THREAD_EVENTS) {
                wev->posted_ready = 1;
            } else {
                wev->ready = 1;
            }
			/*先入隊再處理*/
            if (flags & NGX_POST_EVENTS) {
                ngx_locked_post_event(wev, &ngx_posted_events);
            } else {
                wev->handler(wev);
            }
        }
    }
    return NGX_OK;
}

本文將關(guān)注的兩個epoll函數(shù)也就這么一點代碼了,但整個epoll還有添加事件和刪除事件等的相關(guān)函數(shù),代碼都很簡單,本文就不做具體的分析了。

posted on 2011-07-10 00:54 周強 閱讀(956) 評論(0)  編輯 收藏 引用 所屬分類: nginx

青青草原综合久久大伊人导航_色综合久久天天综合_日日噜噜夜夜狠狠久久丁香五月_热久久这里只有精品
  • <ins id="pjuwb"></ins>
    <blockquote id="pjuwb"><pre id="pjuwb"></pre></blockquote>
    <noscript id="pjuwb"></noscript>
          <sup id="pjuwb"><pre id="pjuwb"></pre></sup>
            <dd id="pjuwb"></dd>
            <abbr id="pjuwb"></abbr>
            国产亚洲成av人在线观看导航 | 日韩亚洲综合在线| 先锋影音国产一区| 亚洲欧美色一区| 性刺激综合网| 久久av资源网站| 久久免费少妇高潮久久精品99| 久久成人综合网| 免费看亚洲片| 99热在线精品观看| 亚洲欧美中文另类| 久久夜色精品国产噜噜av| 欧美激情综合亚洲一二区| 国产精品美女www爽爽爽视频| 国产精品腿扒开做爽爽爽挤奶网站| 国产亚洲激情在线| 亚洲韩国青草视频| 亚洲在线观看视频| 免费成人高清视频| 一区二区激情视频| 欧美一区在线看| 欧美黄色免费| 国产偷久久久精品专区| 亚洲精品国偷自产在线99热| 亚洲欧美日韩国产另类专区| 久久天天躁夜夜躁狠狠躁2022| 亚洲二区在线视频| 亚洲最新视频在线播放| 欧美一区二区三区在线看| 蜜臀久久99精品久久久久久9 | 红杏aⅴ成人免费视频| 亚洲精品中文字| 国产欧美一区二区三区沐欲| 美日韩免费视频| 国产精品第十页| 一区二区三区中文在线观看| 中国av一区| 亚洲福利国产| 久久久激情视频| 国产精品视频内| 一本色道久久99精品综合 | 久久夜色精品国产亚洲aⅴ| 国产精品porn| 亚洲美女在线观看| 免费欧美日韩| 欧美在线关看| 国产欧美日韩视频一区二区三区| 日韩亚洲欧美一区二区三区| 裸体女人亚洲精品一区| 亚洲欧美日韩国产综合在线| 欧美日韩天天操| 亚洲九九精品| 亚洲高清久久久| 欧美成人精品高清在线播放| 亚洲国产精品久久久久秋霞蜜臀| 久久人人爽人人| 久久国产精品久久w女人spa| 国产精品影音先锋| 欧美在线1区| 午夜在线观看欧美| 国产欧美日韩一区二区三区| 性色一区二区| 亚洲欧美日韩精品在线| 国产精品影音先锋| 久久久人成影片一区二区三区观看 | 亚洲国产老妈| 你懂的视频欧美| 亚洲国产一区视频| 亚洲国产欧美一区二区三区丁香婷| 久久综合九色欧美综合狠狠| 亚洲国产日韩一区| 亚洲第一精品影视| 欧美人成免费网站| 亚洲欧美精品伊人久久| 亚洲欧美视频在线观看| 国内精品**久久毛片app| 蜜臀久久99精品久久久画质超高清| 久久久久久有精品国产| 亚洲国产另类久久精品| 亚洲国产综合在线| 欧美色一级片| 久久久99精品免费观看不卡| 久久久久久久久久久久久女国产乱| 在线观看日韩欧美| 亚洲第一页中文字幕| 欧美色视频在线| 国产精品国产精品| 国产精品一区二区三区久久久| 一本高清dvd不卡在线观看| 99热免费精品在线观看| 国产综合色在线| 亚洲国产精品va在线看黑人动漫| 欧美日韩免费看| 久久久水蜜桃av免费网站| 欧美va亚洲va日韩∨a综合色| 一本色道久久| 欧美在线一区二区三区| 亚洲人体1000| 亚洲欧美日韩在线观看a三区| 亚洲第一色中文字幕| 99riav久久精品riav| 国产在线一区二区三区四区| 亚洲国产欧美日韩精品| 国产亚洲福利| 日韩香蕉视频| 亚洲精品1234| 欧美一区二视频| 亚洲香蕉网站| 美女脱光内衣内裤视频久久网站| 欧美亚洲日本一区| 欧美日本亚洲视频| 欧美成人免费在线视频| 国产日韩精品一区二区三区| 亚洲片国产一区一级在线观看| 国产亚洲人成a一在线v站 | 国产精品成人播放| 亚洲第一福利在线观看| 国产亚洲精久久久久久| av72成人在线| 亚洲免费观看高清在线观看| 久久久久久久欧美精品| 欧美一站二站| 国产精品毛片高清在线完整版| 亚洲国产成人高清精品| 影视先锋久久| 久久精品亚洲| 噜噜噜91成人网| 国产亚洲人成网站在线观看| 亚洲淫性视频| 亚洲欧洲av一区二区| 欧美日韩中国免费专区在线看| 欧美成在线观看| 在线电影一区| 麻豆91精品91久久久的内涵| 麻豆成人在线| 激情久久久久久久| 久久精品国产免费观看| 久久亚洲综合色| 精品成人国产| 久久综合九色欧美综合狠狠| 欧美成在线观看| 亚洲日韩中文字幕在线播放| 欧美va亚洲va国产综合| 91久久极品少妇xxxxⅹ软件| 亚洲毛片网站| 欧美日韩午夜| 亚洲欧美日韩国产精品| 久久久久国色av免费观看性色| 国产在线麻豆精品观看| 久久视频精品在线| 亚洲黄色一区| 国产精品午夜国产小视频| 欧美凹凸一区二区三区视频| 亚洲电影免费观看高清完整版在线| 久久精品视频在线| 欧美韩国一区| 亚洲一区在线观看免费观看电影高清| 国产精品成人一区二区三区吃奶| 亚洲性感激情| 久久久久国产精品一区三寸| 在线观看亚洲视频| 欧美国产精品日韩| 一本色道久久99精品综合| 欧美亚洲免费高清在线观看| 国产综合视频在线观看| 欧美大片91| 亚洲视频精品在线| 蜜臀av性久久久久蜜臀aⅴ| 日韩视频免费看| 国产伦理精品不卡| 噜噜噜在线观看免费视频日韩| 日韩视频精品在线观看| 久久精品一区蜜桃臀影院| 亚洲国产成人午夜在线一区| 欧美日韩在线播放三区四区| 欧美在线免费观看亚洲| 亚洲人体1000| 久久这里有精品15一区二区三区| 亚洲精品在线三区| 国产欧美一区二区视频| 欧美成人a视频| 午夜精品一区二区三区在线视| 你懂的国产精品| 欧美亚洲一区在线| 日韩视频不卡中文| 国内成人精品2018免费看 | 亚洲视频在线观看一区| 免费视频一区二区三区在线观看| 亚洲精品综合在线| 国产亚洲成av人片在线观看桃| 欧美另类69精品久久久久9999| 亚洲欧美日韩区| 日韩视频在线一区二区三区| 久久综合五月| 欧美一二三区在线观看| 一本色道88久久加勒比精品| 在线精品福利| 精品动漫3d一区二区三区免费| 国产精品久久久久久影院8一贰佰 国产精品久久久久久影视 | 亚洲国产精品成人va在线观看|