<ruby id="bdb3f"></ruby>

    <p id="bdb3f"><cite id="bdb3f"></cite></p>

      <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
        <p id="bdb3f"><cite id="bdb3f"></cite></p>

          <pre id="bdb3f"></pre>
          <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

          <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
          <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

          <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                <ruby id="bdb3f"></ruby>

                合規國際互聯網加速 OSASE為企業客戶提供高速穩定SD-WAN國際加速解決方案。 廣告
                C程序在進行真正的編譯之前都要進行預編譯。 我們看看fdevent系統中的一些宏: ~~~ #if defined(HAVE_EPOLL_CTL) && defined(HAVE_SYS_EPOLL_H) # if defined HAVE_STDINT_H # include <stdint.h> # endif # define USE_LINUX_EPOLL # include <sys/epoll.h> #endif #if defined HAVE_POLL && (defined(HAVE_SYS_POLL_H) || defined(HAVE_POLL_H)) # define USE_POLL # ifdef HAVE_POLL_H # include <poll.h> # else # include <sys/poll.h> # endif # if defined HAVE_SIGTIMEDWAIT && defined(__linux__) # define USE_LINUX_SIGIO # include <signal.h> # endif #endif //…… ~~~ 上面的宏判斷系統中是否有對應的多路IO系統,如果有,就定義對應的USE_XXX宏。 預編譯完這些宏以后,對于當前系統中有的多路IO系統,就會有對應的USE_XXX符號被定義。預編譯器接著運行,將那些不需要的代碼都忽略。 fdevent.h中對所有可能的多路IO系統都定義了初始化函數: ~~~ int fdevent_select_init(fdevents * ev); int fdevent_poll_init(fdevents * ev); int fdevent_linux_rtsig_init(fdevents * ev); int fdevent_linux_sysepoll_init(fdevents * ev); int fdevent_solaris_devpoll_init(fdevents * ev); int fdevent_freebsd_kqueue_init(fdevents * ev); ~~~ 因此,對于系統中沒有的多路IO系統對應的初始化函數,預編譯結束后,這些初始化函數被定義為報錯函數。如epoll對應的為: ~~~ #ifdef USE_LINUX_EPOLL /* 當定義了epoll時,epoll的函數實現代碼 */ #else /* 當未定義epoll時,epoll只實現init函數(這是必須的,因為該函數在fdevent.h中定義了),并將它實現為報錯函數 */ int fdevent_linux_sysepoll_init(fdevents *ev) { UNUSED(ev); fprintf(stderr, "%s.%d: linux-sysepoll not supported, try to set server.event-handler = \"poll\" or \"select\"\n", __FILE__, __LINE__); return -1; } #endif ~~~ 預編譯后,開始真正的編譯。我們假設系統中只有epoll。 首先,我們看一看配置中有關fdevent的設置。進入configfile.c文件中的config_set_defaults()函數。函數的一開始就有這么一個定義: ~~~ struct ev_map { fdevent_handler_t et; const char *name; } event_handlers[] = { /* * - poll is most reliable - select works everywhere - * linux-* are experimental */ #ifdef USE_POLL {FDEVENT_HANDLER_POLL, "poll"}, #endif #ifdef USE_SELECT {FDEVENT_HANDLER_SELECT, "select"}, #endif #ifdef USE_LINUX_EPOLL {FDEVENT_HANDLER_LINUX_SYSEPOLL, "linux-sysepoll"}, #endif #ifdef USE_LINUX_SIGIO {FDEVENT_HANDLER_LINUX_RTSIG, "linux-rtsig"}, #endif #ifdef USE_SOLARIS_DEVPOLL {FDEVENT_HANDLER_SOLARIS_DEVPOLL, "solaris-devpoll"}, #endif #ifdef USE_FREEBSD_KQUEUE {FDEVENT_HANDLER_FREEBSD_KQUEUE, "freebsd-kqueue"}, {FDEVENT_HANDLER_FREEBSD_KQUEUE, "kqueue"}, #endif {FDEVENT_HANDLER_UNSET, NULL} }; ~~~ 上面定義了一個struct ev_map類型的數組。數組的內容是當前系統中存在的多路IO系統的類型和名稱。這里排序很有意思,從注釋中可以看出,poll排在最前因為最可靠,select其次因為支持最廣泛,epoll第三因為是最好的。 在這里,如果配置文件有配置,那么按配置文件來,如果沒配置,則取上面數組中的第一個。以下是配置文件的格式: ~~~ ## set the event-handler (read the performance ##section in the manual) server.event-handler = "freebsd-kqueue" # needed on OS X ~~~ 接下來我們看server.c中的main函數。 前面有一些是設置fd數量的,其中select比較特殊需要特別處理,fd數量一個是系統的限制,一個是用戶配置的限制。 當程序產生子進程后,在子進程中執行的第一條語句就是初始化fdevent系統: ~~~ if (NULL == (srv->ev = fdevent_init(srv->max_fds + 1, srv->event_handler))) { log_error_write(srv, __FILE__, __LINE__, "s", "fdevent_init failed"); return -1; } ~~~ 進入fdevent_init()函數: ~~~ /** * 初始化文件描述符事件數組fdevent */ fdevents *fdevent_init(size_t maxfds, fdevent_handler_t type) { fdevents *ev; //內存被初始化為0 ev = calloc(1, sizeof(*ev)); //分配數組 ev->fdarray = calloc(maxfds, sizeof(*ev->fdarray)); ev->maxfds = maxfds; //根據設定的多路IO的類型進行初始化。 switch (type) { case FDEVENT_HANDLER_POLL: if (0 != fdevent_poll_init(ev)) { fprintf(stderr, "%s.%d: event-handler poll failed\n", __FILE__, __LINE__); return NULL; } break; case FDEVENT_HANDLER_SELECT: if (0 != fdevent_select_init(ev)) { fprintf(stderr, "%s.%d: event-handler select failed\n", __FILE__, __LINE__); return NULL; } break; case FDEVENT_HANDLER_LINUX_RTSIG: if (0 != fdevent_linux_rtsig_init(ev)) { fprintf(stderr, "%s.%d: event-handler linux-rtsig failed, try to set server.event-handler = \"poll\" or \"select\"\n", __FILE__, __LINE__); return NULL; } break; case FDEVENT_HANDLER_LINUX_SYSEPOLL: if (0 != fdevent_linux_sysepoll_init(ev)) { fprintf(stderr, "%s.%d: event-handler linux-sysepoll failed, try to set server.event-handler = \"poll\" or \"select\"\n", __FILE__, __LINE__); return NULL; } break; case FDEVENT_HANDLER_SOLARIS_DEVPOLL: if (0 != fdevent_solaris_devpoll_init(ev)) { fprintf(stderr, "%s.%d: event-handler solaris-devpoll failed, try to set server.event-handler = \"poll\" or \"select\"\n", __FILE__, __LINE__); return NULL; } break; case FDEVENT_HANDLER_FREEBSD_KQUEUE: if (0 != fdevent_freebsd_kqueue_init(ev)) { fprintf(stderr, "%s.%d: event-handler freebsd-kqueue failed, try to set server.event-handler = \"poll\" or \"select\"\n", __FILE__, __LINE__); return NULL; } break; default: fprintf(stderr, "%s.%d: event-handler is unknown, try to set server.event-handler = \"poll\" or \"select\"\n", __FILE__, __LINE__); return NULL; } return ev; } ~~~ fdevent_init()函數根據fdevent_handler_t的值調用相應的初始化函數。我們進入fdevent_linux_sysepoll_init()函數: ~~~ int fdevent_linux_sysepoll_init(fdevents * ev) { ev->type = FDEVENT_HANDLER_LINUX_SYSEPOLL; #define SET(x) \ ev->x = fdevent_linux_sysepoll_##x; /* 通過SET宏對fdevents結構體中的函數指針賦值。然后創建epoll,最后做一些設置。*/ SET(free); SET(poll); SET(event_del); SET(event_add); SET(event_next_fdndx); SET(event_get_fd); SET(event_get_revent); //創建epoll if (-1 == (ev->epoll_fd = epoll_create(ev->maxfds))) { fprintf(stderr, "%s.%d: epoll_create failed (%s), try to set server.event-handler = \"poll\" or \"select\"\n", __FILE__, __LINE__, strerror(errno)); return -1; } //設置epoll_fd為運行exec()函數時關閉。 if (-1 == fcntl(ev->epoll_fd, F_SETFD, FD_CLOEXEC)) { fprintf(stderr, "%s.%d: epoll_create failed (%s), try to set server.event-handler = \"poll\" or \"select\"\n", __FILE__, __LINE__, strerror(errno)); close(ev->epoll_fd); return -1; } //創建fd事件數組。在epoll_wait函數中使用。 //存儲發生了IO事件的fd和對應的IO事件。 ev->epoll_events = malloc(ev->maxfds * sizeof(*ev->epoll_events)); return 0; } ~~~ 至此fdevent的初始化工作全部完成。
                  <ruby id="bdb3f"></ruby>

                  <p id="bdb3f"><cite id="bdb3f"></cite></p>

                    <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
                      <p id="bdb3f"><cite id="bdb3f"></cite></p>

                        <pre id="bdb3f"></pre>
                        <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

                        <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
                        <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

                        <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                              <ruby id="bdb3f"></ruby>

                              哎呀哎呀视频在线观看