日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 运维知识 > linux >内容正文

linux

linux io端口复用,Linux系统IO复用接口(select、poll、epoll)

發布時間:2024/4/17 linux 29 豆豆
生活随笔 收集整理的這篇文章主要介紹了 linux io端口复用,Linux系统IO复用接口(select、poll、epoll) 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

epoll僅僅是一個異步事件的通知機制,其本身并不作任何的IO讀寫操作,它只負責告訴你是不是可以讀或可以寫了,而具體的讀寫操作,還要應用程序自己來完成。epoll僅提供這種機制是非常好的,它保持了事件通知與IO操作之間彼此的獨立性,使得epoll的使用更加靈活。

接口介紹

int epoll_create(int size)

該函數生成一個epoll專用的文件描述符。它其實是在內核申請一空間,用來存放你想關注的fd上是否發生的事件。size就是你在這個epoll fd上能關注的最大fd數,這個參數不同于select()中的第一個參數,給出最大監聽的fd+1的值。需要注意的是,當創建好epoll句柄后,它就會占用一個fd值,在linux下如果查看/proc/進程id/fd/,是能夠看到這個fd的,所以在使用完epoll后,必須調用close()關閉,否則可能導致fd被耗盡。

int epoll_ctl(int epfd, int op, int fd, struct epoll_event *event)

該函數用于控制某個epoll文件描述符上的事件,可以注冊事件,修改事件,刪除事件。

epfd:由 epoll_create生成的epoll專用的文件描述符;

op:要進行的操作例如注冊事件,可能的取值:

1)EPOLL_CTL_ADD 注冊新的fd到epfd中;

2)EPOLL_CTL_MOD修改已經注冊的fd的監聽事件;

3)EPOLL_CTL_DEL 從epfd中刪除一個fd;

fd:需要監聽的fd

event:指向epoll_event的指針,告訴內核需要監聽的事件,常用的事件類型:

1)EPOLLIN :表示對應的文件描述符可以讀;

2)EPOLLOUT:表示對應的文件描述符可以寫;

3)EPOLLPRI:表示對應的文件描述符有緊急的數據可讀(這里應該表示有帶外數據到來);

4)EPOLLERR:表示對應的文件描述符發生錯誤;

5)EPOLLHUP:表示對應的文件描述符被掛斷;

6)EPOLLET: 將EPOLL設為邊緣觸發(Edge Triggered)模式,這是相對于水平觸發(Level Triggered)來說的。

7)EPOLLONESHOT:只監聽一次事件,當監聽完這次事件之后,如果還需要繼續監聽這個socket的話,需要再次把這個socket加入到EPOLL隊列里。

如果調用成功返回0,不成功返回-1

int epoll_wait(int epfd,struct epoll_event * events,int maxevents,int timeout)

該函數用于輪詢I/O事件的發生,如果發生則將發生的fd和事件類型放入到events數組中。 并且將注冊在epfd上的fd的事件類型給清空,所以如果下一個循環你還要關注這個fd的話,則需要用epoll_ctl(epfd,EPOLL_CTL_MOD,fd,&ev)來重新設置fd的事件類型。這時不用EPOLL_CTL_ADD,因為fd并未清空,只是事件類型清空。

epfd:由epoll_create生成的epoll專用的文件描述符;

epoll_event:用于回傳待處理事件的數組;

maxevents:每次能處理的事件數;

timeout:等待I/O事件發生的超時值,為0的時候表示馬上返回,為-1的時候表示一直等下去,直到有事件返回。

epoll程序基本框架:

for( ; ; )

{

nfds = epoll_wait(epfd,events,20,500);

for(i=0;i

{

if(events[i].data.fd==listenfd) //有新的連接

{

connfd = accept(listenfd,(sockaddr *)&clientaddr, &clilen); //accept這個連接

ev.data.fd=connfd;

ev.events=EPOLLIN|EPOLLET;

epoll_ctl(epfd,EPOLL_CTL_ADD,connfd,&ev); //將新的fd添加到epoll的監聽隊列中

}

else if( events[i].events&EPOLLIN ) //接收到數據,讀socket

{

n = read(sockfd, line, MAXLINE)) < 0 //讀

ev.data.ptr = md; //md為自定義類型,添加數據

ev.events=EPOLLOUT|EPOLLET;

epoll_ctl(epfd,EPOLL_CTL_MOD,sockfd,&ev);//修改標識符,等待下一個循環時發送數據,異步處理的精髓

}

else if(events[i].events&EPOLLOUT) //有數據待發送,寫socket

{

struct myepoll_data* md = (myepoll_data*)events[i].data.ptr; //取數據

sockfd = md->fd;

send( sockfd, md->ptr, strlen((char*)md->ptr), 0 ); //發送數據

ev.data.fd=sockfd;

ev.events=EPOLLIN|EPOLLET;

epoll_ctl(epfd,EPOLL_CTL_MOD,sockfd,&ev); //修改標識符,等待下一個循環時接收數據

}

else

{

//其他的處理

}

}

}

接口比較

Linux提供了select、poll、epoll接口來實現IO復用,三者的原型如下所示,本文從參數、實現、性能等方面對三者進行對比。

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

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

int epoll_wait(int epfd, struct epoll_event *events, int maxevents, int timeout);

select的第一個參數nfds為fdset集合中最大描述符值加1,fdset是一個位數組,其大小限制為__FD_SETSIZE(1024),select的第二三四個參數表示需要關注讀、寫、錯誤事件的文件描述符位數組,這些參數既是輸入參數也是輸出參數,可能會被內核修改用于標示哪些描述符上發生了關注的事件。所以每次調用select前都需要重新初始化fdset。select對應于內核中的sys_select調用,sys_select首先將第二三四個參數指向的fd_set拷貝到內核,然后對每個被SET的描述符調用進行poll,并記錄在臨時結果中(fdset),如果有事件發生,select會將臨時結果寫到用戶空間并返回;當輪詢一遍后沒有任何事件發生時,如果指定了超時時間,則select會睡眠到超時,睡眠結束后再進行一次輪詢,并將臨時結果寫到用戶空間,然后返回。select返回后,需要逐一檢查關注的描述符是否被SET(事件是否發生)。

poll與select不同,通過一個pollfd數組向內核傳遞需要關注的事件,故沒有描述符個數的限制,pollfd中的events字段和revents分別用于標示關注的事件和發生的事件,故pollfd數組只需要被初始化一次。poll的實現機制與select類似,其對應內核中的sys_poll,只不過poll向內核傳遞pollfd數組,然后對pollfd中的每個描述符進行poll,相比處理fdset來說,poll效率更高。

epoll通過epoll_create創建一個用于epoll輪詢的描述符,通過epoll_ctl添加/修改/刪除事件,通過epoll_wait檢查事件,epoll不是通過輪詢,而是通過在等待的描述符上注冊回調函數,當事件發生時,回調函數負責把發生的事件存儲在就緒事件鏈表中,最后寫到用戶空間。epoll返回后,該參數指向的緩沖區中即為發生的事件,即epoll返回時已經明確的知道哪個fd發生了事件,不用再一個個比對。這樣就提高了效率。同時select的FD_SETSIZE是有限止的,而epoll是沒有限止的只與系統資源有關。epoll不會隨著監聽fd數目的增長而降低效率,因為select采用輪詢方式,輪詢的fd數目越多,自然耗時越多,而epoll是觸發式的,所以效率高。

與50位技術專家面對面20年技術見證,附贈技術全景圖

總結

以上是生活随笔為你收集整理的linux io端口复用,Linux系统IO复用接口(select、poll、epoll)的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。