當前位置:編程學習大全網 - 源碼下載 - windows select模型 和linux的區別

windows select模型 和linux的區別

windows select模型

在widows下提供了眾多非阻塞的I/O模型,如select、WSAAsyncSelect、WSAEventSelect、overlapped、completion port,其中IO completion port(IOCP)提供了較好的伸縮性,在windows應用比較廣泛

說明:而select模型主要是解決在單壹線程模式下只能處理壹個套接字的問題,這樣可以避免線程膨脹問題,但是。。。下面看完原型再講起不足之處

select模型:winsock庫主要有兩個版本,這裏主要以winsock2版本為說明,select模型

int select(int nfds,fd_set* readfds,fd_set* writefds,fd_set* exceptfds,const struct timeval* timeout);

其實主要是兩者采用的標準壹致,所以接口基本跟linux壹致,不過nfds在windows其實是沒有意義的,主要是為了兼容其他版本

處理過程:假設以read為例,在這裏windows主要是先將套接字s添加到readfds集合中,然後等待select函數返回,在select函數裏面會移除沒有未決的

I/O操作的套接字句柄,即已經處理過的IO套接字句柄,然後看s是否認仍然還是readfs集合中,在就說明s可讀了,但是這裏面可讀,不壹定有數據

有幾種情況都會引發:數據可讀、連接關閉/重啟/中斷、監聽套接字被調用,此時還有連接未決,accept函數接受新的套接字成功

不足:其實添加到fd_set套接字數量是有限制的,winsock2.h定義的64,自定義也不超過1024,因為值太大,會對服務器的性能有影響,更高的就是可伸縮的IOCP

linux select模型

其實原理跟windows是差不多的,只是處理過程在底層上有點區別

模型:int select(int maxfd,fd_set*readfds,fd_set* writefds,fd_set*exceptfds,const struct timeval*timeout)

這裏主要是maxfd,文件描述符的範圍,比待檢測的最大文件描述符大1

處理過程:也是先將監控的文件添加到文件描述符集合中,調用select監控,判斷文件是否發生變化,但是在底層調用的確是poll方法;首先使用poll_wait將等待隊列添加到poll_table中,返回描述符的掩碼

poll原型:unsigned int (*poll)(struct file*filp,poll_wait* wait)

看如下壹個簡單的處理過程

unsigned int mem_poll(struct file *filp, poll_table *wait)

{

struct mem_dev *dev = filp->private_data;

unsigned int mask = 0;

/*將等待隊列添加到poll_table */

poll_wait(filp, &dev->inq, wait);

if (have_data)

mask |= POLLIN | POLLRDNORM; /* readable */

return mask;

}

在這裏只是添加隊列,返回可讀可寫的掩碼,真正阻塞的不是這裏,是在do_select(...)函數中,在linux內核fs/select.c裏面

int do_select(int n, fd_set_bits *fds, struct timespec *end_time)這個函數

if (file) {

f_op = file->f_op;

mask = DEFAULT_POLLMASK;

if (f_op && f_op->poll) {

wait_key_set(wait, in, out, bit);

mask = (*f_op->poll)(file, wait);

}

這裏面是先判斷文件存在,然後讀取妳自己定義的操作設備I/O的f_op函數,這裏有壹個默認的mask,接著才判斷然後返回描述符mask = (*f_op->poll)(file, wait);用於區分當前哪個集合被觸發了;接著判斷f_op&f_op->poll在這裏我們默認定義了poll函數,所以這裏會進入此判斷語句,mask = (*f_op->poll)(file, wait);這個就是調用默認的poll函數進行處理,關鍵的是如何區分不同的讀、寫、異常過程?

(mask & POLLIN_SET) && (in & bit),這裏面就是對當前的可讀、寫、異常的&&過程,就是為了判斷和區分當前的套接字只是某壹個具體的fd_set集合下;當然某壹個套接字也可能同時在可讀可寫裏面,這時候兩個會進行判斷。

if (retval || timed_out || signal_pending(current))

break;

上面的retval如果為0,且其他也不滿足就會導致空循環狀態,就處於阻塞狀態了

推薦妳看看linux就該這麽學,地址3w(dot)linuxprobe(dot)com,good luck

  • 上一篇:潘神的迷宮中的配角
  • 下一篇:影音同畫配音社團的成員簡介
  • copyright 2024編程學習大全網