6.1 ETモードが非ブロックモードで動作するように設定する理由
読書や必要性が読み取りまたは書き込みエラーが完了するまでETモードで書き込みをするので(読書のため、実際のバイト数を読んだときに停止させることができ、要求されたバイト数よりも小さい)、および非ブロックでない場合は、ファイル記述子ならば、本が読まれているか、または書き込みが決勝で閉塞することにバインドされています。これは、他のファイルディスクリプタタスクスターブその結果、イベントがepoll_waitでブロックすることはできません。
ETとLT 6.2の違い
LT:トリガレベル、効率は、特に、大流量の大同時場合、ETトリガよりも低くなります。しかし、LTのための比較的低いコーディング要件は、問題が発生する可能性はありません。LT-モードサービスのパフォーマンスが書かれている:限りのデータが取得されていないとして、カーネルはあなたをお知らせしていきますので、イベントを逃す心配はありません。
ET:エッジトリガ、効率は、同時、大流量の場合には、LTよりもはるかに少ないファイルディスクリプタシステムコール、したがって高い効率が非常に高いです。しかし、高いプログラミング要件に、各要求、または損失の状況のイベントが発生しやすいの取り扱いは注意が必要です。
ここで列子はLTとETとの間の差を示すことである(モード両方の非ブロッキング、ブロッキングは言わないで、効率が低すぎます)。
あなたは、現在の接続で、すぐそこに確立することができるリターンコールを受け入れ、[次のイベントがepoll_wait通知を待つ、と同じことを選択した場合、LTモードを使用します。
私達accpetリターンコールがあり、現在の外側の確立に加えて、参加している場合でも、ETのために、すぐに、リターン-1 errnoを持つ== EAGAINになるまで、それは循環私達accpetを継続する必要もれるepoll_waitすることはできません
本質的に:並列効率を向上させるためにシステムコールを低減することによりLT、ETモデルと比較します。
6.3楽屋インタビューの質問テンセントによって開発されました
Linuxのファイルディスクリプタのモデルレベル(LT)トリガモードを使用して、ソケットを書き込むことができたとき、それはイベントのソケットが書くことができますトリガ停止します、どのように対処するには?
最初の最も一般的な方法:
ソケットソケットにデータを書き込むだけで、その後のepollに参加し、イベントを書き込むことができます待っているのに必要な時間。書き込みイベントを受信した後、書き込みやデータを送信するために通話を送信します。すべてのデータが終了すると、ソケットはファイルディスクリプタを削除されます。
この方法の欠点は、送信データが小さい場合であっても、我々はまた、ソケットのepoll、中に書いた後に除去のepoll、特定の操作のコストに参加する必要があり、ということです。
改善された方法:
ソケットファイルディスクリプタに参加しない初めに、ソケットにデータを書き込む必要がある、との直接呼び出しは書き込みやデータを送信する送信します。戻りEAGAIN場合、ソケットファイルディスクリプタは、従動ファイルディスクリプタの書き込みデータを追加し、全体のデータ送信が完了された後、ファイルディスクリプタを除去します。
このアプローチの利点は次のとおりです。あまりデータがときのepollイベント処理を回避し、効率を向上させることができます。
どのような状況下ではET 6.4
あなたがプログラムの効率を向上させたいときには、非常にシンプル。
最後に、のepollインスタンスを添付:
(クリックしてここに)折り畳まれたり展開
- 書式#include <sysの/ socket.h>に
- 書式#include <sysの/ wait.h>
- 書式#include <netinetの/ in.h>
- 書式#include <netinetの/ tcp.h>
- 書式#include <sysの/ epoll.h>
- 書式#include <sysの/ sendfile.h>
- 書式#include <sysの/ stat.h>
- 書式#include <unistd.h>
- 書式#include <stdio.hに>
- 書式#include <stdlib.h>に含ま
- 書式#include <string.hの>
- 書式#include <strings.h>
- 書式#include <fcntl.h>
- 書式#include <errno.hを>
- #define MAX_EVENTS 10
- #define PORT 8080
- //セットのソケット接続が非ブロックモードであります
- 無効setnonblocking(int型の数sockfd){
- int型は付き合えません。
- OPTS = fcntlの(数sockfd、F_GETFL)。
- IF(OPTS <0){
- perrorは( "のfcntl(F_GETFL)\ N");
- 出口(1)。
- }
- OPTS =(optsの| O_NONBLOCK);
- IF(fcntlの(数sockfd、F_SETFL、オプト)<0){
- perrorは( "のfcntl(F_SETFL)\ N");
- 出口(1)。
- }
- }
- {int型のmain()
- 構造体epoll_eventはEVは、イベントは[MAX_EVENTS];イベントを追加する責任// EV、イベントが戻りイベントを受け取ります
- int型addrlenは、listenfd、conn_sock、nfds個、epfdに存在、FD、I、NREAD、N。
- 構造体は、ローカル、リモートのsockaddr_in。
- CHAR [BUFSIZ] BUF。
- ソケットを聞く//を作成します。
- IF((listenfd =ソケット(AF_INET、SOCK_STREAM、0))<0){
- perrorは( "数sockfdの\ nを");
- 出口(1)。
- }
- setnonblocking(listenfd); // listenfdノンブロッキングセット[1]
- BZERO(&ローカル、はsizeof(ローカル))。
- local.sin_family = AF_INET;
- local.sin_addr.s_addr = htonl(INADDR_ANY);;
- local.sin_port = htons(PORT)。
- IF(バインド(listenfd、(いるsockaddr *)&地域、はsizeof(ローカル))<0){
- perrorは( "バインド\ nを");
- 出口(1)。
- }
- 聞く(listenfd、20);
- epfdに存在= epoll_create(MAX_EVENTS)。
- IF(epfdに存在== -1){
- perrorは( "epoll_create");
- 出口(EXIT_FAILURE)。
- }
- ev.events = EPOLLIN。
- ev.data.fd = listenfd。
- IF(epoll_ctl(epfdに存在、EPOLL_CTL_ADD、listenfd、&EV)== -1){//监听listenfd
- perrorは( "epoll_ctl:listen_sock");
- 出口(EXIT_FAILURE)。
- }
- ために (;;) {
- nfds個=イベントがepoll_wait(epfdに存在、イベント、MAX_EVENTS、-1)。
- IF(nfds個== -1){
- perrorは( "epoll_pwait");
- 出口(EXIT_FAILURE)。
- }
- 用(i = 0; iはnfds個の<; ++ I){
- FD =イベント[I] .data.fd。
- IF(FD == listenfd){
- 一方、((conn_sock =受け入れる(listenfd、(構造体のsockaddr *)&リモート、
- (size_t *)&addrlenは))> 0){
- setnonblocking(conn_sock); //設定し、次のETモードは、非ブロッキングを設定します
- ev.events = EPOLLIN | EPOLLET;
- ev.data.fd = conn_sock。
- IF(epoll_ctl(epfdに存在、EPOLL_CTL_ADD、conn_sock、&EV)== -1){//读监听
- perrorは( "epoll_ctl:追加"); //接続ソケット
- 出口(EXIT_FAILURE)。
- }
- }
- IF(conn_sock == -1){
- (errnoに!= EAGAIN &&のerrno!= ECONNABORTED場合
- &&のerrno!= EPROTO &&のerrno!= EINTR)
- perrorは( "受け入れ");
- }
- 持続する;
- }
- IF(イベント[I] .events&EPOLLIN){
- n = 0です。
- 一方、((NREAD =読み取る(FD、BUF + N、BUFSIZ-1))> 0){//読み取る次読み取られたET
- N + = NREAD。
- }
- もし(NREAD == -1 &&のerrno!= EAGAIN){
- perrorは( "読み取りエラー");
- }
- ev.data.fd = FD;
- ev.events =イベント[i]は.events | EPOLLOUT; // MOD OUT
- (epoll_ctl(epfdに存在、EPOLL_CTL_MOD、FD&EV)== -1){もし
- perrorは( "epoll_ctl:MOD");
- }
- }
- IF(イベント[I] .events&EPOLLOUT){
- sprintf(BUF、 "HTTP / 1.1 200 OK \ R \ nContent長:%のDの\ r \ nの\ rを\ nHello世界"、11);
- INT NWRITE、DATA_SIZE = STRLEN(BUF)。
- N = DATA_SIZE。
- 一方、(N> 0){
- NWRITE =ライト(FD、BUF + DATA_SIZE - N、N); // ETデータが書き込まれるが書き込まれました
- {(NWRITE <N)の場合
- もし(NWRITE == -1 &&のerrno!= EAGAIN){
- perrorは( "書き込みエラー");
- }
- ブレーク;
- }
- N - = NWRITE。
- }
- クローズ(FD)。
- }
- }
- }
- 0を返します。
- }