新聞中心
Linux操作系統(tǒng)作為一個(gè)開源、自由的操作系統(tǒng),其運(yùn)行速度快、安全穩(wěn)定、容易維護(hù)等優(yōu)點(diǎn),已經(jīng)被廣泛應(yīng)用于各種設(shè)備和場景。在Linux系統(tǒng)中,select函數(shù)是常用的I/O復(fù)用函數(shù),它可以實(shí)現(xiàn)同時(shí)監(jiān)聽多個(gè)I/O事件,提高程序的效率和可靠性。本文將深入剖析Linux Select函數(shù)的使用方法,希望能幫助讀者更好地理解和使用該函數(shù)。

創(chuàng)新互聯(lián)于2013年成立,是專業(yè)互聯(lián)網(wǎng)技術(shù)服務(wù)公司,擁有項(xiàng)目網(wǎng)站設(shè)計(jì)、成都做網(wǎng)站網(wǎng)站策劃,項(xiàng)目實(shí)施與項(xiàng)目整合能力。我們以讓每一個(gè)夢想脫穎而出為使命,1280元紫金做網(wǎng)站,已為上家服務(wù),為紫金各地企業(yè)和個(gè)人服務(wù),聯(lián)系電話:13518219792
一、Select函數(shù)介紹
Select函數(shù)是一種I/O多路復(fù)用機(jī)制,用于同時(shí)監(jiān)聽多個(gè)I/O事件。當(dāng)監(jiān)視的任何一種事件發(fā)生時(shí),select函數(shù)就會(huì)返回,并通知應(yīng)用程序發(fā)生的事件類型。select函數(shù)的基本語法如下:
int select(int nfds, fd_set *readfds, fd_set *writefds, fd_set *exceptfds, struct timeval *timeout);
參數(shù)說明:
1. nfds:監(jiān)視的更大文件描述符,即需要監(jiān)聽事件的文件描述符的更大值加1。
2. readfds:需要監(jiān)聽讀事件的文件描述符。
3. writefds:需要監(jiān)聽寫事件的文件描述符。
4. exceptfds:需要監(jiān)聽異常事件的文件描述符。
5. timeout:超時(shí)時(shí)間,可以讓select函數(shù)在等待一段時(shí)間后超時(shí)返回。
返回值說明:
1. 返回-1:表示select函數(shù)調(diào)用失敗。
2. 返回0:表示在超時(shí)時(shí)間內(nèi)沒有任何事件發(fā)生。
3. 返回大于0的整數(shù):表示有事件發(fā)生,返回值表示有多少個(gè)文件描述符有事件發(fā)生。
由上述語法可知,select函數(shù)的調(diào)用方式較為復(fù)雜,需注意各參數(shù)的設(shè)置和使用方式。
二、Select函數(shù)使用方法
(一) 函數(shù)調(diào)用模式
在使用Select函數(shù)時(shí),應(yīng)該首先考慮Select函數(shù)的調(diào)用模式。Select函數(shù)在調(diào)用時(shí)有兩種模式:阻塞模式和非阻塞模式。在阻塞模式下,當(dāng)Select函數(shù)未檢測到I/O事件時(shí),應(yīng)用程序會(huì)一直被阻塞,直到有事件發(fā)生后才返回。而在非阻塞模式下,當(dāng)Select函數(shù)未檢測到I/O事件時(shí),應(yīng)用程序不會(huì)被阻塞,會(huì)立即返回。非阻塞模式通常用于提高程序的效率和響應(yīng)速度。
(二) 文件描述符的設(shè)置
在使用Select函數(shù)時(shí),需要設(shè)置文件描述符的。文件描述符是文件操作函數(shù)中的一種參數(shù),其通過整數(shù)來標(biāo)識(shí)已打開的文件。在使用Select函數(shù)時(shí),需要將需要監(jiān)聽的文件描述符添加到對應(yīng)的中去。對于不需要監(jiān)聽的文件描述符,則不應(yīng)該添加到對應(yīng)的中。在使用文件描述符時(shí),可以通過以下函數(shù)進(jìn)行設(shè)置操作:
1. FD_ZERO(fd_set *set):將指定的文件描述符清空。
2. FD_SET(int fd, fd_set *set):將指定的文件描述符添加到中。
3. FD_CLR(int fd, fd_set *set):將指定的文件描述符從中刪除。
4. FD_ISSET(int fd, fd_set *set):判斷指定的文件描述符是否在中。
需要注意的是,在設(shè)置和使用fd_set結(jié)構(gòu)體時(shí),不要直接修改底層文件描述符fd_set中的描述符,而應(yīng)該使用fd_set結(jié)構(gòu)體中提供的函數(shù)。
(三) Select函數(shù)的超時(shí)設(shè)置
Select函數(shù)可以設(shè)置超時(shí)時(shí)間,這條語句可以在函數(shù)調(diào)用之前或之后設(shè)置。當(dāng)Select函數(shù)超過指定的時(shí)間后,即使沒有I/O事件發(fā)生,函數(shù)也會(huì)自動(dòng)返回,以防止程序一直被阻塞。timeout參數(shù)是一個(gè)結(jié)構(gòu)體,里面包含了兩個(gè)變量:tv_sec表示等待時(shí)間的整秒部分,tv_usec表示等待時(shí)間的微秒部分。需要注意的是,當(dāng)timeout設(shè)置為NULL時(shí),Select函數(shù)會(huì)一直等待I/O事件的發(fā)生,直到有事件發(fā)生才會(huì)返回。
(四) Select函數(shù)的錯(cuò)誤處理
在使用Select函數(shù)時(shí),需要注意錯(cuò)誤處理。當(dāng)Select函數(shù)返回-1時(shí),表示函數(shù)調(diào)用出錯(cuò)。這時(shí)應(yīng)該使用perror()函數(shù)打印出錯(cuò)誤信息。錯(cuò)誤的原因可能是傳入函數(shù)的參數(shù)不合法,也可能是系統(tǒng)資源不足等。正確處理Select函數(shù)的返回值和錯(cuò)誤信息可以使程序更加穩(wěn)定和安全。
(五) Select函數(shù)的示例程序
下面給出一個(gè)簡單的Select函數(shù)示例程序,以演示Select函數(shù)的基本使用方法。
“`c
#include
#include
#include
#include
#include
#include
#include
#include
#define PORT 8080
#define BUF_SIZE 1024
int mn(int argc, char *argv[]) {
int listenfd, connfd;
struct sockaddr_in servaddr, clientaddr;
socklen_t clientlen = sizeof(clientaddr);
char buf[BUF_SIZE];
fd_set readfds;
int maxfd;
listenfd = socket(AF_INET, SOCK_STREAM, 0);
if (listenfd
perror(“socket error”);
exit(1);
}
memset(&servaddr, 0, sizeof(servaddr));
servaddr.sin_family = AF_INET;
servaddr.sin_port = htons(PORT);
servaddr.sin_addr.s_addr = htonl(INADDR_ANY);
if (bind(listenfd, (struct sockaddr*) &servaddr, sizeof(servaddr))
perror(“bind error”);
exit(1);
}
if (listen(listenfd, 5)
perror(“l(fā)isten error”);
exit(1);
}
FD_ZERO(&readfds);
FD_SET(listenfd, &readfds);
maxfd = listenfd;
while (1) {
int ret = select(maxfd+1, &readfds, NULL, NULL, NULL);
if (ret
perror(“select error”);
exit(1);
} else if (ret == 0) {
printf(“select timeout\n”);
continue;
}
if (FD_ISSET(listenfd, &readfds)) {
connfd = accept(listenfd, (struct sockaddr*) &clientaddr, &clientlen);
if (connfd
perror(“accept error”);
exit(1);
}
printf(“accept a new client: %s:%d\n”, inet_ntoa(clientaddr.sin_addr), ntohs(clientaddr.sin_port));
FD_SET(connfd, &readfds);
maxfd = connfd > maxfd ? connfd : maxfd;
} else {
int fd;
for (fd = listenfd+1; fd
if (FD_ISSET(fd, &readfds)) {
int len = recv(fd, buf, sizeof(buf), 0);
if (len
perror(“recv error”);
exit(1);
} else if (len == 0) {
printf(“client closed\n”);
close(fd);
FD_CLR(fd, &readfds);
} else {
printf(“recv from client: %s\n”, buf);
send(fd, buf, len, 0);
}
}
}
}
}
close(listenfd);
return 0;
}
“`
上述代碼是一個(gè)簡單的TCP服務(wù)器代碼。該代碼使用了Select函數(shù)實(shí)現(xiàn)并發(fā)處理多個(gè)客戶端的請求。代碼中首先創(chuàng)建了一個(gè)監(jiān)聽套接字,設(shè)置了服務(wù)器的IP和端口,并將其綁定到監(jiān)聽套接字上。然后,將監(jiān)聽套接字添加到讀取文件描述符中,并初始化所有的客戶端描述符為空。在循環(huán)中,通過調(diào)用Select函數(shù)等待所有文件描述符中的一個(gè)或多個(gè)文件描述符將準(zhǔn)備好進(jìn)行I/O操作。當(dāng)Select函數(shù)返回時(shí),使用FD_ISSET()函數(shù)輪詢讀取文件描述符,判斷哪個(gè)讀取事件已經(jīng)準(zhǔn)備好了,并接收或發(fā)送數(shù)據(jù)。當(dāng)有新連接到來時(shí),使用accept()函數(shù)處理連接請求,并將客戶端描述符添加到讀取文件描述符中。
三、
成都網(wǎng)站建設(shè)公司-創(chuàng)新互聯(lián)為您提供網(wǎng)站建設(shè)、網(wǎng)站制作、網(wǎng)頁設(shè)計(jì)及定制高端網(wǎng)站建設(shè)服務(wù)!
Linux內(nèi)核(七)輪詢操作
在用戶程序中,select()和poll()也是與設(shè)備阻塞和非阻塞訪問相關(guān)的內(nèi)容。
使用非阻塞IO的應(yīng)用程序通常會(huì)使用select()和poll()系統(tǒng)調(diào)用查詢是否可以對設(shè)備進(jìn)行無阻塞的訪問。
select()和poll()系統(tǒng)調(diào)用最終會(huì)使設(shè)備驅(qū)動(dòng)中的poll()函數(shù)執(zhí)行,在后續(xù)的Linux內(nèi)核版本中還引入了epoll(),即擴(kuò)展的poll()。
select()和poll()系統(tǒng)調(diào)用的本質(zhì)是一樣的,前者在BSD Unix中引入,后者在System V中引入。
應(yīng)用程序中使用最廣泛的是BSD Unix中引入的select()系統(tǒng)調(diào)用,原型如下:
如下圖所示,
之一次對n個(gè)文件進(jìn)行select()的時(shí)候,若任何一個(gè)文件滿足要求,select()就直接返回;
第二次再進(jìn)行select()的時(shí)候,沒有文件滿足讀寫要求,select()的進(jìn)程阻塞且睡眠。
由于調(diào)用select()的時(shí)候,每個(gè)驅(qū)動(dòng)的poll()接口都會(huì)被調(diào)用到。實(shí)際上執(zhí)行select()的進(jìn)程被掛到了每個(gè)驅(qū)動(dòng)的等待隊(duì)列上,可以被任何一個(gè)驅(qū)動(dòng)喚醒。如果FDn變得可讀寫,select()返回。
poll()的功能和實(shí)現(xiàn)原理與select()類似,其原型函數(shù)為:
當(dāng)多路復(fù)用的文件數(shù)量龐大、IO流量頻繁的時(shí)候,一般不太適合使用select()和poll(),這種情況下select()和poll()表現(xiàn)較差,推薦使用epoll()。
使用epoll()更大的好處就是不會(huì)隨著fd數(shù)目的增長而降低效率,select()則會(huì)隨沖廳著fd數(shù)量增大性能明顯下降。
相關(guān)接口:
創(chuàng)建一個(gè)epoll()的句柄,size用來告訴內(nèi)核要監(jiān)聽多少個(gè)fd,當(dāng)創(chuàng)建好epoll()句柄時(shí),它本身也會(huì)占用一個(gè)fd值,所以在使用完epoll()后,必須調(diào)用close()關(guān)閉。
告訴內(nèi)核要監(jiān)聽什么類型的事件:
之一個(gè)參數(shù)epfd是epoll_create()的返回值,
第二個(gè)參數(shù)表示動(dòng)作,包含散洞隱:
第3個(gè)參數(shù)是需要監(jiān)聽的fd,
第4個(gè)參數(shù)是告訴內(nèi)核需要監(jiān)聽的事件類型,struct_epoll_event結(jié)構(gòu)如下:
events可以是以下幾個(gè)宏的”或“:
一般來說,當(dāng)涉及的fd數(shù)量較少時(shí),使用select是合適的;如果涉及的fd很多,如顫判在大規(guī)模并發(fā)的服務(wù)器中監(jiān)聽許多socket的時(shí)候,則不太適合選用select,適合使用epoll。
關(guān)于linux下select函數(shù)問題
需不需要是寫api的人決定的, 他覺得有用你就得給, 想多沒意義
都檢查
nfds: 需要檢查的文件描述字個(gè)數(shù)(即檢查到胡明fd_set的第幾位),數(shù)值應(yīng)該比三組fd_set中所含的更大fd值更大,一般設(shè)為三組fd_set中所含的更大fd值加1(如在readset, writeset, exceptset中所含更大的fd為5,則nfds=6,因?yàn)閒d是從0開始的 )。設(shè)這個(gè)值是為了提高效率,使函數(shù)不必檢查fd_set的所有1024位。 否則函數(shù)默認(rèn)會(huì)檢查到更大值
至于你那個(gè)補(bǔ)充內(nèi)容,是這樣的 當(dāng)調(diào)用悄做余select()時(shí),由內(nèi)核根據(jù)IO狀態(tài)修改fe_set的內(nèi)容,由此來通知執(zhí)行了select()的進(jìn)程哪一socket或文件可讀寫。 這個(gè) 是系統(tǒng)內(nèi)核負(fù)責(zé)管理的,如果fd1或fd2那個(gè)一啟滾旦有變化,系統(tǒng)內(nèi)核會(huì)修改其內(nèi)容就通知select的進(jìn)程了,如果fd1 fd2都可讀 首先肯定有個(gè)先后順序,會(huì)記錄下來,挨個(gè)處理。
關(guān)于select函數(shù)在linux下的問題
因?yàn)長INUX下的標(biāo)準(zhǔn)輸森稿出stdout,是行緩沖的,緩沖區(qū)大小8192字節(jié)是一個(gè)典型值.
必須遇到字符’\n’才真正刷新緩沖區(qū)輸出到屏幕上,或者輸出緩沖區(qū)被填滿也會(huì)輸出到屏幕。
我估計(jì),你等足夠長的時(shí)間,搏春伍等你的修改后的基或程序把輸出緩沖區(qū)填滿,會(huì)一次性的打印出一大堆a(bǔ)bc.
linux select 詳解的介紹就聊到這里吧,感謝你花時(shí)間閱讀本站內(nèi)容,更多關(guān)于linux select 詳解,深入剖析Linux Select函數(shù)使用方法,Linux內(nèi)核(七)輪詢操作,關(guān)于linux下select函數(shù)問題,關(guān)于select函數(shù)在linux下的問題的信息別忘了在本站進(jìn)行查找喔。
四川成都云服務(wù)器租用托管【創(chuàng)新互聯(lián)】提供各地服務(wù)器租用,電信服務(wù)器托管、移動(dòng)服務(wù)器托管、聯(lián)通服務(wù)器托管,云服務(wù)器虛擬主機(jī)租用。成都機(jī)房托管咨詢:13518219792
創(chuàng)新互聯(lián)(www.cdcxhl.com)擁有10多年的服務(wù)器租用、服務(wù)器托管、云服務(wù)器、虛擬主機(jī)、網(wǎng)站系統(tǒng)開發(fā)經(jīng)驗(yàn)、開啟建站+互聯(lián)網(wǎng)銷售服務(wù),與企業(yè)客戶共同成長,共創(chuàng)價(jià)值。
網(wǎng)站欄目:深入剖析LinuxSelect函數(shù)使用方法(linuxselect詳解)
鏈接URL:http://fisionsoft.com.cn/article/dpsjesj.html


咨詢
建站咨詢
