<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國際加速解決方案。 廣告
                - I/O多路服用 - 信號驅動I/O - Linux特有的epoll編程接口 O_NONBLOCK非阻塞IO ### 什么是文件描述符? 文件描述符是用于指代被打開的文件 ### IO多路復用 可以同時檢測多個文件描述符,select(), poll();這兩個系統調用要么等待文件描述符成為就緒態,要么在調用中設定一個超時時間; #### select ```c // returns number of read file descriptors, 0 on timeout, -1 on error #include <sys/time.h> #include <sys/select.h> int select(int nfds, fd_set *readfds, fd_set *writefds, fd_set *exceptfds, struct timeval *timeout) ``` - nfds 需要檢測的文件描述符最大符號,通過設置該值,select()變得更加效率,因為不需要檢測大于nfds的其他文件描述符號 - readfds 檢測輸入是否就緒的文件描述符集合(保存結果的地方) - writefds 檢測輸出是否就緒的文件描述符集合(保存結果的地方) - exceptfds 檢測異常情況的文件描述符集合(保存結果的地方) - timeout 為NULL時,select將一直阻塞,timeout結構如下: ```c struct timeval { time_t tv_sec; suseconds_t tv_usec; // 微妙 } ``` 文件描述符集合由宏來操作 ```c #include <sys/select.h> void FD_ZERO(fd_set *fdset) void FD_SET(int fd, fd_set *fdset) void FD_CLR(int fd, fd_set *fdset) void FD_ISSET(int fd, fd_set *fdset) ``` - FD_ZERO() 將fdset指向的文件描述符集合初始化為空 - FD_SET() 將fd添加到fdset文件描述符集合 - FD_CLR() 將fd從fdset文件描述符集合移除 - FD_ISSET() fd是否為fdset文件描述符集合成員 文件描述符集合容量限制有FD_SETSIZE決定 #### poll ```c // returns number of read file descriptors, 0 on timeout,or -1 on error #include <poll.h> int poll(struct pollfd fds[], nfds_t nfds, int timeout) ``` struct pollfd結構如下: ```c struct pollfd { int fd; short events; short revents; } ``` ### select和poll就緒態 select和poll只會告訴我們IO操作是否阻塞,而不是告訴我們能否成功傳輸數據 不同類型的描述符 ### 信號驅動 進程可以處理其他任務,當有數據寫入到文件描述符時,內核向調用數據的進程發送信號;在檢測大量文件描述符時,信號驅動比select()和poll()有優勢 ### epoll epoll優點如下: - epoll是Linux特有的,可以同時檢測多個文件描述符,并且性能比select()和poll()好; - 支持兩種模式,水平觸發(level trigger),邊緣觸發(edge trigger),默認是LT模式 #### epoll api ```c int epoll_create(int size) ``` 創建一個epoll句柄,size表示告訴內核要監控多少個fd;創建之后會占用一個fd,在使用晚時需要close掉 ```c int epoll_ctl(int epfd, int op, int fd, struct epoll_event *event) ``` 事件注冊函數 - epfd 由epoll_create創建返回的句柄 - op - EPOLL_CTL_ADD 添加一個fd到epfd - EPOLL_CTL_MOD 修改已注冊的fd的監聽事件 - EPOLL_CTL_DEL 從epfd刪除一個fd - fd 需要監聽的fd - struct epoll_event *event 監聽事件,結構如下: ```c struct epoll_event { __unit32_t events; // 例如EPOLLIN,EPOLLOUT epoll_data_t data; } ``` ```C // 返回需要處理的事件數目 int epoll_wait(int epfd, struct epoll_event *event, int maxevents, int timeout) ``` 等待事件的發生 ### libEvent libEvent提供了檢查文件描述符IO事件的抽象;Libevent底層機制能夠以透明的方式應用select(),poll(),epoll(),信號驅動等任意一種技術 ### 工作模式(水平觸發,邊緣觸發) - 水平觸發:檢測到文件描述符有事件發送并通知應用程序,應用程序可以不立即處理事件 - 邊緣觸發:檢測到文件描述符有事件發送并通知應用程序,應用程序必須立即處理事件 各種IO模式通知模式如下: |IO模式|水平觸發|邊緣觸發| |:---:|:---:|:---:| |select(),poll()|Y|N| |信號驅動|N|Y| |epoll|Y|Y|
                  <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>

                              哎呀哎呀视频在线观看