小小書童記錄select

來源:互聯網
上載者:User
這是一個建立於 的文章,其中的資訊可能已經有所發展或是發生改變。

Select IO複用模型是上個世紀90年代的東西,受限於當時的電腦硬軟體的限制,這種技術隨著epoll的出現逐漸被取代,但它畢竟風光過。瞭解曆史才能更好的展望未來,每一個有情懷的碼農都不應該一味抬頭看遠方,時而低頭凝視大地,不亦樂乎~

瞭解select之前,我們需要瞭解下位元影像(bitmap),bitmap其實就是將對象映射到具體的一個bit位上來,表示對象存在或者被標記。bitmap演算法有節省記憶體和快速查詢等特點,所以適合處理海量資料的排序和查詢。這種古老而牛逼的技術在資料庫,作業系統上都有很廣泛的應用。好的,下面引入select中使用到bitmap演算法的幾個API函數,也是在使用select這種IO複用技術時經常使用到的。

int FD_ZERO(fd_set *fdset);    // 複位int FD_CLR(int fd, fd_set *fdset);   // 清零int FD_SET(int fd, fd_set *fd_set);   // 設定int FD_ISSET(int fd, fd_set *fdset);  // 測試設定

這幾個函數主要完成具體 fdfd_set rset 映射關係的處理。看下fd_set的儲存結構:

#ifndef FD_SETSIZE#define FD_SETSIZE  1024#endif#define NBBY    8       /* number of bits in a byte */typedef long    fd_mask;#define NFDBITS (sizeof (fd_mask) * NBBY)   /* bits per mask */#define howmany(x,y)    (((x)+((y)-1))/(y))typedef struct _types_fd_set {    fd_mask fds_bits[howmany(FD_SETSIZE, NFDBITS)];} _types_fd_set;

清楚的看到,一個long類型8個位元組,這樣fds_bits就有1024/64 = 16 即16個64bit的數組,每一個數組64bit。設定和清零這兩個操作是位操作,很方便,自己寫了一個BitMapGolang代碼,這裡也順便貼出:

func (b *BitSet) Set(i uint) {        ....    b.set[i>>6] = b.set[i>>6] | (1 << (i & (64 - 1)))}func (b *BitSet) Clear(i uint) {    ....    b.set[i>>6] &^= 1 << (i & (64 - 1))}

好了,知道fdset的儲存結構和簡單設定之後,可以看下selectIO模型中的另外一個API:

int select(int maxfdp, fd_set *readset, fd_set *writeset, fd_set *exceptset,struct timeval *timeout);

其中有兩個參數需要說明下:

  1. 第一個參數是timeout, 它代表select逾時時間。該值有三種狀態:timeout == NULL 無條件等待。 select函數將返回 -1, erro設為 EINTR,表示被迫中斷。timeout->tv_sec == 0 &&timeout->tv_usec == 0 不等待,直接返回。timeout->tv_sec != 0 || timeout->tv_usec != 0 等待指定的時間,select返回0表示在規定時間內沒有fd讀寫或者例外狀況事件發生。
struct timeval  {        long tv_sec;   /*秒 */        long tv_usec;  /*微秒 */   }
  1. 第二個參數 maxfdp,這個是檔案描述符fd的最大值加1。每次調用select之前都需要算出最大的fd,作為maxfd。

關於select的核心實現部分,網上有很多文章進行了詳細的描述,這裡就不再贅述。好的,這裡還是不落俗套地提下select的缺點:<1> 描述符(FD)數量問題 。<2> IO效率隨FD的增加而線性下降。select隨FD的增加效能下降的問題, 在使用方式上可以感受到:使用者態需要每次select之前複位所有fd,然後select之後還得遍曆所有fd找到可讀寫或異常的fd。但至今沒有對select做過benchmark

這裡隨便帶上poll小弟:

int poll (struct pollfd *fds, unsigned int nfds, int timeout);

其中pollfd的資料結構:

struct pollfd {    int fd; /* file descriptor */    short events; /* requested events to watch */    short revents; /* returned events witnessed */};

poll方式並沒有採用selectfdset方式,而是每一個fd都有一個自己的pollfd資料結構,裡面存放除了fd外,還存放events事件類型,這樣poll就沒有fd個數的上限問題了,但它仍然需要遍曆fds拿到可讀寫或異常的fd。這點跟select還是一樣的。

好了,小小書童簡單記錄下,end~

相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.