• <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>
            posts - 297,  comments - 15,  trackbacks - 0
            1 功能介紹
                 epoll與select/poll不同的一點是,它是由一組系統(tǒng)調(diào)用組成。
                 int epoll_create(int size);
                 int epoll_ctl(int epfd, int op, int fd, struct epoll_event *event);
                 int epoll_wait(int epfd, struct epoll_event *events,
                                   int maxevents, int timeout);
                 epoll相關系統(tǒng)調(diào)用是在Linux 2.5.44開始引入的。該系統(tǒng)調(diào)用針對傳統(tǒng)的selec
            t/poll系統(tǒng)調(diào)用的不足,設計上作了很大的改動。select/poll的缺點在于:
                 1.每次調(diào)用時要重復地從用戶態(tài)讀入?yún)?shù)。
                 2.每次調(diào)用時要重復地掃描文件描述符。
                 3.每次在調(diào)用開始時,要把當前進程放入各個文件描述符的等待隊列。在調(diào)用結(jié)
            束后,又把進程從各個等待隊列中刪除。
                 在實際應用中,select/poll監(jiān)視的文件描述符可能會非常多,如果每次只是返回
            一小部分,那么,這種情況下select/poll顯得不夠高效。epoll的設計思路,是把s
            elect/poll單個的操作拆分為1個epoll_create+多個epoll_ctrl+一個wait。此外,
            內(nèi)核針對epoll操作添加了一個文件系統(tǒng)”eventpollfs”,每一個或者多個要監(jiān)視的
            文件描述符都有一個對應的eventpollfs文件系統(tǒng)的inode節(jié)點,主要信息保存在eve
            ntpoll結(jié)構(gòu)體中。而被監(jiān)視的文件的重要信息則保存在epitem結(jié)構(gòu)體中。所以他們
            是一對多的關系。
                 由于在執(zhí)行epoll_create和epoll_ctrl時,已經(jīng)把用戶態(tài)的信息保存到內(nèi)核態(tài)了
            ,所以之后即使反復地調(diào)用epoll_wait,也不會重復地拷貝參數(shù),掃描文件描述符,
            反復地把當前進程放入/放出等待隊列。這樣就避免了以上的三個缺點。
                 接下去看看它們的實現(xiàn):
            2 關鍵結(jié)構(gòu)體:
            /* Wrapper struct used by poll queueing */
            struct ep_pqueue {
                     poll_table pt;
                     struct epitem *epi;
            };
                 這個結(jié)構(gòu)體類似于select/poll中的struct poll_wqueues。由于epoll需要在內(nèi)核
            態(tài)保存大量信息,所以光光一個回調(diào)函數(shù)指針已經(jīng)不能滿足要求,所以在這里引入了
            一個新的結(jié)構(gòu)體struct epitem。
            /*
            * Each file descriptor added to the eventpoll interface will
            * have an entry of this type linked to the hash.
            */
            struct epitem {
                     /* RB-Tree node used to link this structure to the eventpoll rb
            -tree */
                     struct rb_node rbn;
            紅黑樹,用來保存eventpoll
                     /* List header used to link this structure to the eventpoll rea
            dy list */
                     struct list_head rdllink;
            雙向鏈表,用來保存已經(jīng)完成的eventpoll
                     /* The file descriptor information this item refers to */
                     struct epoll_filefd ffd;
            這個結(jié)構(gòu)體對應的被監(jiān)聽的文件描述符信息
                     /* Number of active wait queue attached to poll operations */
                     int nwait;
            poll操作中事件的個數(shù)
                     /* List containing poll wait queues */
                     struct list_head pwqlist;
            雙向鏈表,保存著被監(jiān)視文件的等待隊列,功能類似于select/poll中的poll_tab
            le
                     /* The "container" of this item */
                     struct eventpoll *ep;
            指向eventpoll,多個epitem對應一個eventpoll
                     /* The structure that describe the interested events and the so
            urce fd */
                     struct epoll_event event;
            記錄發(fā)生的事件和對應的fd
                     /*
                      * Used to keep track of the usage count of the structure. This
            avoids
                      * that the structure will desappear from underneath our proces
            sing.
                      */
                     atomic_t usecnt;
            引用計數(shù)
                     /* List header used to link this item to the "struct file" item
            s list */
                     struct list_head fllink;
            雙向鏈表,用來鏈接被監(jiān)視的文件描述符對應的struct file。因為file里有f_ep
            _link,用來保存所有監(jiān)視這個文件的epoll節(jié)點
                     /* List header used to link the item to the transfer list */
                     struct list_head txlink;
            雙向鏈表,用來保存?zhèn)鬏旉犃?br>         /*
                      * This is used during the collection/transfer of events to use
            rspace
                      * to pin items empty events set.
                      */
                     unsigned int revents;
            文件描述符的狀態(tài),在收集和傳輸時用來鎖住空的事件集合
            };
                 該結(jié)構(gòu)體用來保存與epoll節(jié)點關聯(lián)的多個文件描述符,保存的方式是使用紅黑樹
            實現(xiàn)的hash表。至于為什么要保存,下文有詳細解釋。它與被監(jiān)聽的文件描述符一一
            對應。
            struct eventpoll {
                     /* Protect the this structure access */
                     rwlock_t lock;
            讀寫鎖
                     /*
                      * This semaphore is used to ensure that files are not removed
                      * while epoll is using them. This is read-held during the even
            t
                      * collection loop and it is write-held during the file cleanup
                      * path, the epoll file exit code and the ctl operations.
                      */
                     struct rw_semaphore sem;
            讀寫信號量
                     /* Wait queue used by sys_epoll_wait() */
                     wait_queue_head_t wq;
                     /* Wait queue used by file->poll() */
                     wait_queue_head_t poll_wait;
                     /* List of ready file descriptors */
                     struct list_head rdllist;
            已經(jīng)完成的操作事件的隊列。
                     /* RB-Tree root used to store monitored fd structs */
                     struct rb_root rbr;
            保存epoll監(jiān)視的文件描述符
            };
                 這個結(jié)構(gòu)體保存了epoll文件描述符的擴展信息,它被保存在file結(jié)構(gòu)體的priva
            te_data中。它與epoll文件節(jié)點一一對應。通常一個epoll文件節(jié)點對應多個被監(jiān)視
            的文件描述符。所以一個eventpoll結(jié)構(gòu)體會對應多個epitem結(jié)構(gòu)體。
                 那么,epoll中的等待事件放在哪里呢?見下面
            /* Wait structure used by the poll hooks */
            struct eppoll_entry {
                     /* List header used to link this structure to the "struct epite
            m" */
                     struct list_head llink;
                     /* The "base" pointer is set to the container "struct epitem" *
            /
                     void *base;
                     /*
                      * Wait queue item that will be linked to the target file wait
                      * queue head.
                      */
                     wait_queue_t wait;
                     /* The wait queue head that linked the "wait" wait queue item *
            /
                     wait_queue_head_t *whead;
            };
                 與select/poll的struct poll_table_entry相比,epoll的表示等待隊列節(jié)點的結(jié)
            構(gòu)體只是稍有不同,與struct poll_table_entry比較一下。
            struct poll_table_entry {
                     struct file * filp;
                     wait_queue_t wait;
                     wait_queue_head_t * wait_address;
            };
                 由于epitem對應一個被監(jiān)視的文件,所以通過base可以方便地得到被監(jiān)視的文件
            信息。又因為一個文件可能有多個事件發(fā)生,所以用llink鏈接這些事件。
            3 epoll_create的實現(xiàn)
                 epoll_create()的功能是創(chuàng)建一個eventpollfs文件系統(tǒng)的inode節(jié)點。具體由ep
            _getfd()完成。ep_getfd()先調(diào)用ep_eventpoll_inode()創(chuàng)建一個inode節(jié)點,然后
            調(diào)用d_alloc()為inode分配一個dentry。最后把file,dentry,inode三者關聯(lián)起來。
                 在執(zhí)行了ep_getfd()之后,它又調(diào)用了ep_file_init(),分配了eventpoll結(jié)構(gòu)體
            ,并把eventpoll的指針賦給file結(jié)構(gòu)體,這樣eventpoll就與file結(jié)構(gòu)體關聯(lián)起來了

                 需要注意的是epoll_create()的參數(shù)size實際上只是起參考作用,只要它不小于
            等于0,就并不限制這個epoll inode關聯(lián)的文件描述符數(shù)量。
            4 epoll_ctl的實現(xiàn)
                 epoll_ctl的功能是實現(xiàn)一系列操作,如把文件與eventpollfs文件系統(tǒng)的inode節(jié)
            點關聯(lián)起來。這里要介紹一下eventpoll結(jié)構(gòu)體,它保存在file->f_private中,記錄
            了eventpollfs文件系統(tǒng)的inode節(jié)點的重要信息,其中成員rbr保存了該epoll文件節(jié)
            點監(jiān)視的所有文件描述符。組織的方式是一棵紅黑樹,這種結(jié)構(gòu)體在查找節(jié)點時非常
            高效。
                 首先它調(diào)用ep_find()從eventpoll中的紅黑樹獲得epitem結(jié)構(gòu)體。然后根據(jù)op參
            數(shù)的不同而選擇不同的操作。如果op為EPOLL_CTL_ADD,那么正常情況下epitem是不
            可能在eventpoll的紅黑樹中找到的,所以調(diào)用ep_insert創(chuàng)建一個epitem結(jié)構(gòu)體并插
            入到對應的紅黑樹中。
                 ep_insert()首先分配一個epitem對象,對它初始化后,把它放入對應的紅黑樹。
            此外,這個函數(shù)還要作一個操作,就是把當前進程放入對應文件操作的等待隊列。這
            一步是由下面的代碼完成的。
                 init_poll_funcptr(&epq.pt, ep_ptable_queue_proc);
                 。。。
                 revents = tfile->f_op->poll(tfile, &epq.pt);
                 函數(shù)先調(diào)用init_poll_funcptr注冊了一個回調(diào)函數(shù) ep_ptable_queue_proc,這
            個函數(shù)會在調(diào)用f_op->poll時被執(zhí)行。該函數(shù)分配一個epoll等待隊列結(jié)點eppoll_e
            ntry:一方面把它掛到文件操作的等待隊列中,另一方面把它掛到epitem的隊列中
            。此外,它還注冊了一個等待隊列的回調(diào)函數(shù)ep_poll_callback。當文件操作完成,
            喚醒當前進程之前,會調(diào)用ep_poll_callback(),把eventpoll放到epitem的完成隊
            列中,并喚醒等待進程。
                 如果在執(zhí)行f_op->poll以后,發(fā)現(xiàn)被監(jiān)視的文件操作已經(jīng)完成了,那么把它放在
            完成隊列中了,并立即把等待操作的那些進程喚醒。
            5 epoll_wait的實現(xiàn)
                 epoll_wait的工作是等待文件操作完成并返回。
                 它的主體是ep_poll(),該函數(shù)在for循環(huán)中檢查epitem中有沒有已經(jīng)完成的事件
            ,有的話就把結(jié)果返回。沒有的話調(diào)用schedule_timeout()進入休眠,直到進程被再
            度喚醒或者超時。
            6 性能分析
                 epoll機制是針對select/poll的缺陷設計的。通過新引入的eventpollfs文件系統(tǒng)
            ,epoll把參數(shù)拷貝到內(nèi)核態(tài),在每次輪詢時不會重復拷貝。通過把操作拆分為epol
            l_create,epoll_ctl,epoll_wait,避免了重復地遍歷要監(jiān)視的文件描述符。此外,
            由于調(diào)用epoll的進程被喚醒后,只要直接從epitem的完成隊列中找出完成的事件,
            找出完成事件的復雜度由O(N)降到了O(1)。
                 但是epoll的性能提高是有前提的,那就是監(jiān)視的文件描述符非常多,而且每次完
            成操作的文件非常少。所以,epoll能否顯著提高效率,取決于實際的應用場景。這
            方面需要進一步測試。

            轉(zhuǎn)自http://www.freecity.cn/agent/thread.do?id=LinuxDev-48b24eba-c4e53e6f2d89ff3cb039f2c4ed4102e9

            from:

            http://blog.chinaunix.net/u2/67780/showart_2064403.html

            posted on 2010-04-24 22:41 chatler 閱讀(312) 評論(0)  編輯 收藏 引用 所屬分類: Socket
            <2009年11月>
            25262728293031
            1234567
            891011121314
            15161718192021
            22232425262728
            293012345

            常用鏈接

            留言簿(10)

            隨筆分類(307)

            隨筆檔案(297)

            algorithm

            Books_Free_Online

            C++

            database

            Linux

            Linux shell

            linux socket

            misce

            • cloudward
            • 感覺這個博客還是不錯,雖然做的東西和我不大相關,覺得看看還是有好處的

            network

            OSS

            • Google Android
            • Android is a software stack for mobile devices that includes an operating system, middleware and key applications. This early look at the Android SDK provides the tools and APIs necessary to begin developing applications on the Android platform using the Java programming language.
            • os161 file list

            overall

            搜索

            •  

            最新評論

            閱讀排行榜

            評論排行榜

            久久亚洲精品成人av无码网站| 久久国产午夜精品一区二区三区| 国产成人精品久久亚洲| 久久丫精品国产亚洲av不卡| 亚洲AV日韩精品久久久久| 久久精品卫校国产小美女| 久久精品中文字幕一区| 久久综合九色综合久99| 国产欧美久久久精品影院| 狠狠色丁香婷婷久久综合五月| 亚洲伊人久久成综合人影院 | 91精品国产综合久久香蕉| 国产午夜精品理论片久久影视 | 国产精品久久久久jk制服| 久久久久亚洲AV无码网站| 国产亚洲精品美女久久久| 26uuu久久五月天| 亚洲国产精品无码久久青草 | 久久九九久精品国产| 日韩中文久久| 色偷偷88888欧美精品久久久 | AA级片免费看视频久久| 99久久国产综合精品网成人影院| 久久精品国产99久久久香蕉| 久久久国产视频| 久久久久久久久久久久中文字幕| 99久久久精品免费观看国产| 国产精品青草久久久久福利99| 久久99国产精品成人欧美| 精产国品久久一二三产区区别| 国产午夜久久影院| 狠狠色丁香久久婷婷综合_中| 久久99精品久久久久久久久久 | 久久国产乱子伦精品免费强| 久久久久国色AV免费观看| 久久精品国产精品亚洲精品| 91精品国产高清久久久久久io| 香蕉aa三级久久毛片| 国产精品久久国产精麻豆99网站| 一级做a爰片久久毛片毛片| 久久精品国产亚洲网站|