欧美极品高清xxxxhd,国产日产欧美最新,无码AV国产东京热AV无码,国产精品人与动性XXX,国产传媒亚洲综合一区二区,四库影院永久国产精品,毛片免费免费高清视频,福利所导航夜趣136

 找回密碼
 立即注冊

QQ登錄

只需一步,快速開始

搜索
查看: 360|回復: 0
收起左側

select poll, epoll

[復制鏈接]
ID:1154223 發表于 2025-6-16 19:52 | 顯示全部樓層 |閱讀模式
Select,Poll,Epoll是學習I/O多路復用必不可少的一節,這章我將借用對這三個系統調用的講解,進一步加深對于I/O多路復用的理解
首先我們要知道為什么要有I/O多路復用,可以通過一次系統調用,檢查多個文件描述符的狀態。這是 I/O 多路復用的主要優點,相比于非阻塞 I/O,在文件描述符較多的場景下,避免了頻繁的用戶態和內核態的切換,減少了系統調用的開銷。
I/O 多路復用相當于將「遍歷所有文件描述符、通過非阻塞 I/O 查看其是否就緒」的過程從用戶線程移到了內核中,由內核來負責輪詢。
首先回憶一下,I/O多路復用是一種使用少數線程來監聽多數網絡Socket的一種I/O方法,那么我們怎么使用I/O多路復用呢
Select
select使用一個固定大小的位圖來表示文件描述符fd的集合,調用select檢查這些fd的狀態,每次調用select時都會重新構建位圖,并將其傳遞給內核,內核來判斷是否有I/O已經就緒
select的核心數據結構是一個fd_set,        這是一個文件描述符集合,用來管理需要監視的文件描述符
fd_set的核心是一個位圖(大小位1024),每一位對應著文件描述符的狀態,1表示該描述符需要監視,0表示該描述符不需要監視
typedef __kernel_fd_set                fd_set;

#define __FD_SETSIZE        1024

typedef struct {
        unsigned long fds_bits[__FD_SETSIZE / (8 * sizeof(long))];
} __kernel_fd_set;
        select的函數原型如下
int select(int nfds, fd_set *readfds, fd_set *writefds, fd_set *exceptfds, struct timeval *timeout);

        可以看到,有三種fd_set
● readfds -- 可讀事件,用來監視事件是否可讀
● writefds -- 可寫事件,用來監視事件是否可寫
● exceptfds -- 描述符是否有異常情況
● nfds -- 要監視的文件描述符的最大值+1
● timeout -- 可以選擇的監視時間 可以是 阻塞(NULL),立即返回(0),或者指定的等待時間
1. 在調用select的是否我們需要把需要監視的事件通過函數加入到對應的隊列中
2. 進入內核態進行檢查,程序在調用select之后,內核會歷遍對應的fd查看是否符合對應的狀態
  a. 符合:如果符合就把事件加入到readfds當中去
  b. 不符合:如果所有的都不符合就根據timeout來選擇等待的方式和事件
3. 返回,最后會返回符合要求的fd的數量
    while (1) {      
        fd_set rfds;
        fd_set wfds;
        int32_t maxfd = 0, res = 0;
        struct timeval timeout;
        
        timeout.tv_sec = 0;
        timeout.tv_usec = 500;
        
        FD_ZERO(&rfds);
        FD_ZERO(&wfds);
        
        FD_SET(socket1, &rfds);
        FD_SET(socket2, &rfds);
        
        maxfd = socket1 > socket2 ? socket1 : socket2;
        
        res = select(maxfd + 1, &rfds, NULL, NULL, &timeout);
        
        if (res < 0 && errno != EINTR && errno != 0) {
            // log it
            return;
        }
        
        if (FD_ISSET(socket1, &rfds)) {
            // do something
        }
        if (FD_ISSET(socket2, &rfds)) {
            // do something
        }
     }
        上面大致講解了如何使用select,這里其實我們可以很明顯的看出一個缺點的,
1. 就是我們并不返回符合要求的fd,而是把所有的fd都返回,所以返回到用戶態之后我們要進行fd的歷遍最終才能找到有相應的fd,這顯然是比較耗費事件的
回復

使用道具 舉報

您需要登錄后才可以回帖 登錄 | 立即注冊

本版積分規則

小黑屋|51黑電子論壇 |51黑電子論壇6群 QQ 管理員QQ:125739409;技術交流QQ群281945664

Powered by 單片機教程網

快速回復 返回頂部 返回列表