<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>

                ??碼云GVP開源項目 12k star Uniapp+ElementUI 功能強大 支持多語言、二開方便! 廣告
                #### 1.INotify介紹與使用 INotify是一個Linux內核所提供的一種文件系統變化通知機制。它可以為應用程序監控文件系統的變化,如文件的新建、刪除、讀寫等。INotify機制有兩個基本對象,分別為inotify對象與watch對象,都使用文件描述符表示。 inotify對象對應了一個隊列,應用程序可以向inotify對象添加多個監聽。當被監聽的事件發生時,可以通過read()函數從inotify對象中將事件信息讀取出來。Inotify對象可以通過以下方式創建: ``` int inotifyFd = inotify_init(); ``` 而watch對象則用來描述文件系統的變化事件的監聽。它是一個二元組,包括監聽目標和事件掩碼兩個元素。監聽目標是文件系統的一個路徑,可以是文件也可以是文件夾。而事件掩碼則表示了需要需要監聽的事件類型,掩碼中的每一位代表一種事件。可以監聽的事件種類很多,其中就包括文件的創建(IN\_CREATE)與刪除(IN\_DELETE)。讀者可以參閱相關資料以了解其他可監聽的事件種類。以下代碼即可將一個用于監聽輸入設備節點的創建與刪除的watch對象添加到inotify對象中: ``` int wd = inotify_add_watch (inotifyFd, “/dev/input”,IN_CREATE | IN_DELETE); ``` 完成上述watch對象的添加后,當/dev/input/下的設備節點發生創建與刪除操作時,都會將相應的事件信息寫入到inotifyFd所描述的inotify對象中,此時可以通過read()函數從inotifyFd描述符中將事件信息讀取出來。 事件信息使用結構體inotify\_event進行描述: ``` struct inotify_event { __s32 wd; /* 事件對應的Watch對象的描述符 */ __u32 mask; /* 事件類型,例如文件被刪除,此處值為IN_DELETE */ __u32 cookie; __u32 len; /* name字段的長度 */ char name[0]; /* 可變長的字段,用于存儲產生此事件的文件路徑*/ }; ``` 當沒有監聽事件發生時,可以通過如下方式將一個或多個未讀取的事件信息讀取出來: ``` size_t len = read (inotifyFd, events_buf,BUF_LEN); ``` 其中events\_buf是inotify\_event的數組指針,能夠讀取的事件數量由取決于數組的長度。成功讀取事件信息后,便可根據inotify\_event結構體的字段判斷事件類型以及產生事件的文件路徑了。 總結一下INotify機制的使用過程: - 通過inotify\_init()創建一個inotify對象。 - 通過inotify\_add\_watch將一個或多個監聽添加到inotify對象中。 - 通過read()函數從inotify對象中讀取監聽事件。當沒有新事件發生時,inotify對象中無任何可讀數據。 通過INotify機制避免了輪詢文件系統的麻煩,但是還有一個問題,INotify機制并不是通過回調的方式通知事件,而需要使用者主動從inotify對象中進行事件讀取。那么何時才是讀取的最佳時機呢?這就需要借助Linux的另一個優秀的機制Epoll了。 #### 2.Epoll介紹與使用 無論是從設備節點中獲取原始輸入事件還是從inotify對象中讀取文件系統事件,都面臨一個問題,就是這些事件都是偶發的。也就是說,大部分情況下設備節點、inotify對象這些文件描述符中都是無數據可讀的,同時又希望有事件到來時可以盡快地對事件作出反應。為解決這個問題,我們不希望不斷地輪詢這些描述符,也不希望為每個描述符創建一個單獨的線程進行阻塞時的讀取,因為這都將會導致資源的極大浪費。 此時最佳的辦法是使用Epoll機制。Epoll可以使用一次等待監聽多個描述符的可讀/可寫狀態。等待返回時攜帶了可讀的描述符或自定義的數據,使用者可以據此讀取所需的數據后可以再次進入等待。因此不需要為每個描述符創建獨立的線程進行阻塞讀取,避免了資源浪費的同時又可以獲得較快的響應速度。 Epoll機制的接口只有三個函數,十分簡單。 - epoll\_create(int max\_fds):創建一個epoll對象的描述符,之后對epoll的操作均使用這個描述符完成。max\_fds參數表示了此epoll對象可以監聽的描述符的最大數量。 - epoll\_ctl (int epfd, int op,int fd, struct epoll\_event \*event):用于管理注冊事件的函數。這個函數可以增加/刪除/修改事件的注冊。 - int epoll\_wait(int epfd, structepoll\_event \* events, int maxevents, int timeout):用于等待事件的到來。當此函數返回時,events數組參數中將會包含產生事件的文件描述符。 接下來以監控若干描述符可讀事件為例介紹一下epoll的用法。 (1) 創建epoll對象 首先通過epoll\_create()函數創建一個epoll對象: ``` Int epfd = epoll_create(MAX_FDS) ``` (2) 填充epoll\_event結構體 接著為每一個需監控的描述符填充epoll\_event結構體,以描述監控事件,并通過epoll\_ctl()函數將此描述符與epoll\_event結構體注冊進epoll對象。epoll\_event結構體的定義如下: ``` struct epoll_event { __uint32_tevents; /* 事件掩碼,指明了需要監聽的事件種類*/ epoll_data_t data; /* 使用者自定義的數據,當此事件發生時該數據將原封不動地返回給使用者 */ }; ``` epoll\_data\_t聯合體的定義如下,當然,同一時間使用者只能使用一個字段: ``` typedef union epoll_data { void*ptr; int fd; __uint32_t u32; __uint64_t u64; } epoll_data_t; ``` epoll\_event結構中的events字段是一個事件掩碼,用以指明需要監聽的事件種類,同INotify一樣,掩碼的每一位代表了一種事件。常用的事件有EPOLLIN(可讀),EPOLLOUT(可寫),EPOLLERR(描述符發生錯誤),EPOLLHUP(描述符被掛起)等。更多支持的事件讀者可參考相關資料。 data字段是一個聯合體,它讓使用者可以將一些自定義數據加入到事件通知中,當此事件發生時,用戶設置的data字段將會返回給使用者。在實際使用中常設置epoll\_event.data.fd為需要監聽的文件描述符,事件發生時便可以根據epoll\_event.data.fd得知引發事件的描述符。當然也可以設置epoll\_event.data.fd為其他便于識別的數據。 填充epoll\_event的方法如下: ``` structepoll_event eventItem; memset(&eventItem, 0, sizeof(eventItem)); eventItem.events = EPOLLIN | EPOLLERR | EPOLLHUP; // 監聽描述符可讀以及出錯的事件 eventItem.data.fd= listeningFd; // 填寫自定義數據為需要監聽的描述符 ``` 接下來就可以使用epoll\_ctl()將事件注冊進epoll對象了。epoll\_ctl()的參數有四個: - epfd是由epoll\_create()函數所創建的epoll對象的描述符。 - op表示了何種操作,包括EPOLL\_CTL\_ADD/DEL/MOD三種,分別表示增加/刪除/修改注冊事件。 - fd表示了需要監聽的描述符。 - event參數是描述了監聽事件的詳細信息的epoll\_event結構體。 注冊方法如下: ``` // 將事件監聽添加到epoll對象中去 result =epoll_ctl(epfd, EPOLL_CTL_ADD, listeningFd, &eventItem); ``` 重復這個步驟可以將多個文件描述符的多種事件監聽注冊到epoll對象中。完成了監聽的注冊之后,便可以通過epoll\_wait()函數等待事件的到來了。 (3) 使用epoll\_wait()函數等待事件 epoll\_wait()函數將會使調用者陷入等待狀態,直到其注冊的事件之一發生之后才會返回,并且攜帶了剛剛發生的事件的詳細信息。其簽名如下: ``` int epoll_wait(int epfd, struct epoll_event *events, int maxevents, int timeout); ``` - epfd是由epoll\_create()函數所創建的epoll對象描述符。 - events是一個epoll\_event的數組,此函數返回時,事件的信息將被填充至此。 - maxevents表示此次調用最多可以獲取多少個事件,當然,events參數必須能夠足夠容納這么多事件。 - timeout表示等待超時的事件。 epoll\_wait()函數返回值表示獲取了多少個事件。 4\. 處理事件 epoll\_wait返回后,便可以根據events數組中所保存的所有epoll\_event結構體的events字段與data字段識別事件的類型與來源。 Epoll的使用步驟總結如下: - 通過epoll\_create()創建一個epoll對象。 - 為需要監聽的描述符填充epoll\_events結構體,并使用epoll\_ctl()注冊到epoll對象中。 - 使用epoll\_wait()等待事件的發生。 - 根據epoll\_wait()返回的epoll\_events結構體數組判斷事件的類型與來源并進行處理。 - 繼續使用epoll\_wait()等待新事件的發生。 #### 3.INotify與Epoll的小結 INotify與Epoll這兩套由Linux提供的事件監聽機制以最小的開銷解決了文件系統變化以及文件描述符可讀可寫狀態變化的監聽問題。它們是Reader子系統運行的基石,了解了這兩個機制的使用方法之后便為對Reader子系統的分析學習鋪平了道路。
                  <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>

                              哎呀哎呀视频在线观看