如题所述
epollçæ¥å£é常ç®åï¼ä¸å
±å°±ä¸ä¸ªå½æ°ï¼
1. int epoll_create(int size);
å建ä¸ä¸ªepollçå¥æï¼sizeç¨æ¥åè¯å æ ¸è¿ä¸ªçå¬çæ°ç®ä¸å ±æå¤å¤§ãè¿ä¸ªåæ°ä¸åäºselect()ä¸ç第ä¸ä¸ªåæ°ï¼ç»åºæ大çå¬çfd+1çå¼ãéè¦æ³¨æçæ¯ï¼å½å建好epollå¥æåï¼å®å°±æ¯ä¼å ç¨ä¸ä¸ªfdå¼ï¼å¨linuxä¸å¦ææ¥ç/proc/è¿ç¨id/fd/ï¼æ¯è½å¤çå°è¿ä¸ªfdçï¼æ以å¨ä½¿ç¨å®epollåï¼å¿ é¡»è°ç¨close()å ³éï¼å¦åå¯è½å¯¼è´fd被èå°½ã
2. int epoll_ctl(int epfd, int op, int fd, struct epoll_event* event);
epollçäºä»¶æ³¨åå½æ°ï¼å³æ³¨åè¦çå¬çäºä»¶ç±»åã
第ä¸ä¸ªåæ°æ¯epoll_create()çè¿åå¼ï¼
第äºä¸ªåæ°è¡¨ç¤ºå¨ä½ï¼ç¨ä¸ä¸ªå®æ¥è¡¨ç¤ºï¼
EPOLL_CTL_ADDï¼æ³¨åæ°çfdå°epfdä¸ï¼
EPOLL_CTL_MODï¼ä¿®æ¹å·²ç»æ³¨åçfdççå¬äºä»¶ï¼
EPOLL_CTL_DELï¼ä»epfdä¸å é¤ä¸ä¸ªfdï¼
第ä¸ä¸ªåæ°æ¯éè¦çå¬çfdï¼
第å个åæ°æ¯åè¯å æ ¸éè¦çå¬ä»ä¹äºï¼struct epoll_eventç»æå¦ä¸ï¼
struct epoll_event {
__uint32_t events;
epoll_data_t data;
};
typedef union epoll_data {
void *ptr;
int fd;
__uint32_t u32;
__uint64_t u64;
} epoll_data_t;
eventså¯ä»¥æ¯ä»¥ä¸å 个å®çéåï¼
EPOLLIN ï¼ è¡¨ç¤ºå¯¹åºçæ件æ述符å¯ä»¥è¯»ï¼å æ¬å¯¹ç«¯SOCKETæ£å¸¸å ³éï¼ï¼
EPOLLOUTï¼ è¡¨ç¤ºå¯¹åºçæ件æ述符å¯ä»¥åï¼
EPOLLPRIï¼ è¡¨ç¤ºå¯¹åºçæ件æ述符æç´§æ¥çæ°æ®å¯è¯»ï¼è¿éåºè¯¥è¡¨ç¤ºæ带å¤æ°æ®å°æ¥ï¼ï¼
EPOLLERRï¼ è¡¨ç¤ºå¯¹åºçæ件æ述符åçé误ï¼
EPOLLHUPï¼ è¡¨ç¤ºå¯¹åºçæ件æ述符被ææï¼
EPOLLETï¼ å° EPOLL设为边ç¼è§¦å(Edge Triggered)模å¼ï¼é»è®¤ä¸ºæ°´å¹³è§¦åï¼ï¼è¿æ¯ç¸å¯¹äºæ°´å¹³è§¦å(Level Triggered)æ¥è¯´çã
EPOLLONESHOTï¼ åªçå¬ä¸æ¬¡äºä»¶ï¼å½çå¬å®è¿æ¬¡äºä»¶ä¹åï¼å¦æè¿éè¦ç»§ç»çå¬è¿ä¸ªsocketçè¯ï¼éè¦å次æè¿ä¸ªsocketå å ¥å°EPOLLéåé
3. int epoll_wait(int epfd, struct epoll_event *events, int maxevents, int timeout);
çå¾ äºä»¶ç产çãåæ°events ç¨æ¥ä»å æ ¸å¾å°äºä»¶çéåï¼maxevents åä¹å æ ¸è¿ä¸ªevents æå¤å¤§ï¼è¿ä¸ªmaxevents çå¼ä¸è½å¤§äºå建epoll_create()æ¶çsizeï¼åæ°timeoutæ¯è¶ æ¶æ¶é´ï¼æ¯«ç§ï¼0ä¼ç«å³è¿åï¼-1å°ä¸ç¡®å®ï¼ä¹æ说æ³è¯´æ¯æ°¸ä¹ é»å¡ï¼ã该å½æ°è¿åéè¦å¤ççäºä»¶æ°ç®ï¼å¦è¿å0è¡¨ç¤ºå·²è¶ æ¶ã
4. EPOLLäºä»¶æ两ç§æ¨¡åï¼
Edge Triggered (ET) è¾¹ç¼è§¦å åªææ°æ®å°æ¥ï¼æ触åï¼ä¸ç®¡ç¼ååºä¸æ¯å¦è¿ææ°æ®ã
Level Triggered (LT) 水平触å åªè¦ææ°æ®é½ä¼è§¦åã
åå¦æè¿æ ·ä¸ä¸ªä¾åï¼
1. æ们已ç»æä¸ä¸ªç¨æ¥ä»ç®¡éä¸è¯»åæ°æ®çæ件å¥æ(RFD)æ·»å å°epollæ述符
2. è¿ä¸ªæ¶åä»ç®¡éçå¦ä¸ç«¯è¢«åå ¥äº2KBçæ°æ®
3. è°ç¨epoll_wait(2)ï¼å¹¶ä¸å®ä¼è¿åRFDï¼è¯´æå®å·²ç»åå¤å¥½è¯»åæä½
4. ç¶åæ们读åäº1KBçæ°æ®
5. è°ç¨epoll_wait(2)......
Edge Triggered å·¥ä½æ¨¡å¼ï¼
å¦ææ们å¨ç¬¬1æ¥å°RFDæ·»å å°epollæ述符çæ¶å使ç¨äºEPOLLETæ å¿ï¼é£ä¹å¨ç¬¬5æ¥è°ç¨epoll_wait(2)ä¹åå°æå¯è½ä¼æèµ·ï¼å 为å©ä½çæ°æ®è¿åå¨äºæ件çè¾å ¥ç¼å²åºå ï¼èä¸æ°æ®ååºç«¯è¿å¨çå¾ ä¸ä¸ªé对已ç»ååºæ°æ®çåé¦ä¿¡æ¯ãåªæå¨çè§çæ件å¥æä¸åçäºæ个äºä»¶çæ¶å ET å·¥ä½æ¨¡å¼æä¼æ±æ¥äºä»¶ãå æ¤å¨ç¬¬5æ¥çæ¶åï¼è°ç¨è å¯è½ä¼æ¾å¼çå¾ ä»å¨åå¨äºæ件è¾å ¥ç¼å²åºå çå©ä½æ°æ®ãå¨ä¸é¢çä¾åä¸ï¼ä¼æä¸ä¸ªäºä»¶äº§çå¨RFDå¥æä¸ï¼å 为å¨ç¬¬2æ¥æ§è¡äºä¸ä¸ªåæä½ï¼ç¶åï¼äºä»¶å°ä¼å¨ç¬¬3æ¥è¢«éæ¯ãå 为第4 æ¥ç读åæä½æ²¡æ读空æ件è¾å ¥ç¼å²åºå çæ°æ®ï¼å æ¤æ们å¨ç¬¬5 æ¥è°ç¨epoll_wait(2)å®æåï¼æ¯å¦æèµ·æ¯ä¸ç¡®å®çãepollå·¥ä½å¨ET模å¼çæ¶åï¼å¿ 须使ç¨éé»å¡å¥æ¥å£ï¼ä»¥é¿å ç±äºä¸ä¸ªæ件å¥æçé»å¡è¯»/é»å¡åæä½æå¤çå¤ä¸ªæ件æ述符çä»»å¡é¥¿æ»ãæ好以ä¸é¢çæ¹å¼è°ç¨ET模å¼çepollæ¥å£ï¼å¨åé¢ä¼ä»ç»é¿å å¯è½ç缺é·ã
i åºäºéé»å¡æ件å¥æ
ii åªæå½read(2)æè write(2)è¿åEAGAINæ¶æéè¦æèµ·ï¼çå¾ ãä½è¿å¹¶ä¸æ¯è¯´æ¯æ¬¡read()æ¶é½éè¦å¾ªç¯è¯»ï¼ç´å°è¯»å°äº§çä¸ä¸ªEAGAIN æ认为æ¤æ¬¡äºä»¶å¤çå®æï¼å½read()è¿åç读å°çæ°æ®é¿åº¦å°äºè¯·æ±çæ°æ®é¿åº¦æ¶ï¼å°±å¯ä»¥ç¡®å®æ¤æ¶ç¼å²ä¸å·²æ²¡ææ°æ®äºï¼ä¹å°±å¯ä»¥è®¤ä¸ºæ¤äºè¯»äºä»¶å·²å¤çå®æãLevel Triggered å·¥ä½æ¨¡å¼ç¸åçï¼ä»¥LTæ¹å¼è°ç¨epollæ¥å£çæ¶åï¼å®å°±ç¸å½äºä¸ä¸ªé度æ¯è¾å¿«çpoll(2)ï¼å¹¶ä¸æ 论åé¢çæ°æ®æ¯å¦è¢«ä½¿ç¨ï¼å æ¤ä»ä»¬å ·æåæ ·çèè½ãå 为å³ä½¿ä½¿ç¨ET模å¼çepollï¼å¨æ¶å°å¤ä¸ªchunk çæ°æ®çæ¶åä»ç¶ä¼äº§çå¤ä¸ªäºä»¶ãè°ç¨è å¯ä»¥è®¾å®EPOLLONESHOTæ å¿ï¼å¨ epoll_wait(2)æ¶å°äºä»¶åepollä¼ä¸äºä»¶å ³èçæ件å¥æä»epollæ述符ä¸ç¦æ¢æãå æ¤å½EPOLLONESHOT设å®åï¼ä½¿ç¨å¸¦æ EPOLL_CTL_MODæ å¿çepoll_ctl(2)å¤çæ件å¥æå°±æ为è°ç¨è å¿ é¡»ä½çäºæ ã
ç¶å详ç»è§£éET, LT:
LT(level triggered)æ¯ç¼ºççå·¥ä½æ¹å¼ï¼å¹¶ä¸åæ¶æ¯æblock åno-blocksocket.å¨è¿ç§åæ³ä¸ï¼å æ ¸åè¯ä½ ä¸ä¸ªæ件æ述符æ¯å¦å°±ç»ªäºï¼ç¶åä½ å¯ä»¥å¯¹è¿ä¸ªå°±ç»ªçfdè¿è¡IOæä½ãå¦æä½ ä¸ä½ä»»ä½æä½ï¼å æ ¸è¿æ¯ä¼ç»§ç»éç¥ä½ çï¼æ以ï¼è¿ç§æ¨¡å¼ç¼ç¨åºé误å¯è½æ§è¦å°ä¸ç¹ãä¼ ç»çselect/pollé½æ¯è¿ç§æ¨¡åç代表ï¼
ET(edge-triggered)æ¯é«éå·¥ä½æ¹å¼ï¼åªæ¯æno-block socketãå¨è¿ç§æ¨¡å¼ä¸ï¼å½æ述符ä»æªå°±ç»ªå为就绪æ¶ï¼å æ ¸éè¿epollåè¯ä½ ãç¶åå®ä¼åè®¾ä½ ç¥éæ件æ述符已ç»å°±ç»ªï¼å¹¶ä¸ä¸ä¼å为é£ä¸ªæ件æ述符åéæ´å¤ç就绪éç¥ï¼ç´å°ä½ åäºæäºæä½å¯¼è´é£ä¸ªæ件æ述符ä¸å为就绪ç¶æäº(æ¯å¦ï¼ä½ å¨åéï¼æ¥æ¶æè æ¥æ¶è¯·æ±ï¼æè åéæ¥æ¶çæ°æ®å°äºä¸å®éæ¶å¯¼è´äºä¸ä¸ªEWOULDBLOCK é误ï¼ãä½æ¯è¯·æ³¨æï¼å¦æä¸ç´ä¸å¯¹è¿ä¸ªfdä½IOæä½(ä»è导è´å®å次åææªå°±ç»ª)ï¼å æ ¸ä¸ä¼åéæ´å¤çéç¥(only once),ä¸è¿å¨TCPåè®®ä¸ï¼ET模å¼çå éæç¨ä»éè¦æ´å¤çbenchmark确认ï¼è¿å¥è¯ä¸ç解ï¼ã
å¨è®¸å¤æµè¯ä¸æ们ä¼çå°å¦æ没æ大éçidle -connection æè deadconnectionï¼epoll çæç并ä¸ä¼æ¯select/poll é«å¾å¤ï¼ä½æ¯å½æ们éå°å¤§éçidleconnection(ä¾å¦WAN ç¯å¢ä¸åå¨å¤§éçæ ¢éè¿æ¥)ï¼å°±ä¼åç°epoll çæç大大é«äºselect/pollãï¼æªæµè¯ï¼
å¦å¤ï¼å½ä½¿ç¨epollçET模åæ¥å·¥ä½æ¶ï¼å½äº§çäºä¸ä¸ªEPOLLINäºä»¶åï¼è¯»æ°æ®çæ¶åéè¦èèçæ¯å½recv()è¿åç大å°å¦æçäºè¯·æ±ç大å°ï¼é£ä¹å¾æå¯è½æ¯ç¼å²åºè¿ææ°æ®æªè¯»å®ï¼ä¹æå³ç该次äºä»¶è¿æ²¡æå¤çå®ï¼æ以è¿éè¦å次读åï¼
while(rs) {
buflen = recv(activeevents[i].data.fd, buf, sizeof(buf), 0);
if(buflen < 0) {
// ç±äºæ¯éé»å¡ç模å¼,æ以å½errno为EAGAINæ¶,表示å½åç¼å²åºå·²æ æ°æ®å¯è¯»
// å¨è¿éå°±å½ä½æ¯è¯¥æ¬¡äºä»¶å·²å¤çå¤.
if(errno == EAGAIN) {
break;
} else {
return;
}
} else if(buflen == 0) {
// è¿é表示对端çsocketå·²æ£å¸¸å ³é.
}
if(buflen == sizeof(buf)) {
rs = 1; // éè¦å次读å
} else {
rs = 0;
}
}
è¿æï¼åå¦åé端æµé大äºæ¥æ¶ç«¯çæµé(æææ¯epollæå¨çç¨åºè¯»æ¯è½¬åçsocketè¦å¿«),ç±äºæ¯éé»å¡çsocket,é£ä¹send()å½æ°è½ç¶è¿å,ä½å®é ç¼å²åºçæ°æ®å¹¶æªçæ£åç»æ¥æ¶ç«¯,è¿æ ·ä¸æç读ååï¼å½ç¼å²åºæ»¡åä¼äº§çEAGAINé误(åèman send),åæ¶,ä¸çä¼è¿æ¬¡è¯·æ±åéçæ°æ®.æ以,éè¦å°è£ socket_send()çå½æ°ç¨æ¥å¤çè¿ç§æ åµ,该å½æ°ä¼å°½éå°æ°æ®åå®åè¿åï¼è¿å-1 表示åºéãå¨socket_send()å é¨,å½åç¼å²å·²æ»¡(send()è¿å-1,ä¸errno为EAGAIN),é£ä¹ä¼çå¾ ååéè¯.è¿ç§æ¹å¼å¹¶ä¸å¾å®ç¾,å¨ç论ä¸å¯è½ä¼é¿æ¶é´çé»å¡å¨socket_send()å é¨,ä½æ没ææ´å¥½çåæ³.
ssize_t socket_send(int sockfd, const char* buffer, size_t buflen) {
ssize_t tmp;
size_t total = buflen;
const char *p = buffer;
while(1) {
tmp = send(sockfd, p, total, 0);
if(tmp < 0) {
// å½sendæ¶å°ä¿¡å·æ¶,å¯ä»¥ç»§ç»å,ä½è¿éè¿å-1.
if(errno == EINTR)
return -1;
// å½socketæ¯éé»å¡æ¶,å¦è¿åæ¤é误,表示åç¼å²éå已满,
// å¨è¿éå延æ¶ååéè¯.
if(errno == EAGAIN) {
usleep(1000);
continue;
}
return -1;
}
if((size_t)tmp == total)
return buflen;
total -= tmp;
p += tmp;
}
return tmp;
}
1. int epoll_create(int size);
å建ä¸ä¸ªepollçå¥æï¼sizeç¨æ¥åè¯å æ ¸è¿ä¸ªçå¬çæ°ç®ä¸å ±æå¤å¤§ãè¿ä¸ªåæ°ä¸åäºselect()ä¸ç第ä¸ä¸ªåæ°ï¼ç»åºæ大çå¬çfd+1çå¼ãéè¦æ³¨æçæ¯ï¼å½å建好epollå¥æåï¼å®å°±æ¯ä¼å ç¨ä¸ä¸ªfdå¼ï¼å¨linuxä¸å¦ææ¥ç/proc/è¿ç¨id/fd/ï¼æ¯è½å¤çå°è¿ä¸ªfdçï¼æ以å¨ä½¿ç¨å®epollåï¼å¿ é¡»è°ç¨close()å ³éï¼å¦åå¯è½å¯¼è´fd被èå°½ã
2. int epoll_ctl(int epfd, int op, int fd, struct epoll_event* event);
epollçäºä»¶æ³¨åå½æ°ï¼å³æ³¨åè¦çå¬çäºä»¶ç±»åã
第ä¸ä¸ªåæ°æ¯epoll_create()çè¿åå¼ï¼
第äºä¸ªåæ°è¡¨ç¤ºå¨ä½ï¼ç¨ä¸ä¸ªå®æ¥è¡¨ç¤ºï¼
EPOLL_CTL_ADDï¼æ³¨åæ°çfdå°epfdä¸ï¼
EPOLL_CTL_MODï¼ä¿®æ¹å·²ç»æ³¨åçfdççå¬äºä»¶ï¼
EPOLL_CTL_DELï¼ä»epfdä¸å é¤ä¸ä¸ªfdï¼
第ä¸ä¸ªåæ°æ¯éè¦çå¬çfdï¼
第å个åæ°æ¯åè¯å æ ¸éè¦çå¬ä»ä¹äºï¼struct epoll_eventç»æå¦ä¸ï¼
struct epoll_event {
__uint32_t events;
epoll_data_t data;
};
typedef union epoll_data {
void *ptr;
int fd;
__uint32_t u32;
__uint64_t u64;
} epoll_data_t;
eventså¯ä»¥æ¯ä»¥ä¸å 个å®çéåï¼
EPOLLIN ï¼ è¡¨ç¤ºå¯¹åºçæ件æ述符å¯ä»¥è¯»ï¼å æ¬å¯¹ç«¯SOCKETæ£å¸¸å ³éï¼ï¼
EPOLLOUTï¼ è¡¨ç¤ºå¯¹åºçæ件æ述符å¯ä»¥åï¼
EPOLLPRIï¼ è¡¨ç¤ºå¯¹åºçæ件æ述符æç´§æ¥çæ°æ®å¯è¯»ï¼è¿éåºè¯¥è¡¨ç¤ºæ带å¤æ°æ®å°æ¥ï¼ï¼
EPOLLERRï¼ è¡¨ç¤ºå¯¹åºçæ件æ述符åçé误ï¼
EPOLLHUPï¼ è¡¨ç¤ºå¯¹åºçæ件æ述符被ææï¼
EPOLLETï¼ å° EPOLL设为边ç¼è§¦å(Edge Triggered)模å¼ï¼é»è®¤ä¸ºæ°´å¹³è§¦åï¼ï¼è¿æ¯ç¸å¯¹äºæ°´å¹³è§¦å(Level Triggered)æ¥è¯´çã
EPOLLONESHOTï¼ åªçå¬ä¸æ¬¡äºä»¶ï¼å½çå¬å®è¿æ¬¡äºä»¶ä¹åï¼å¦æè¿éè¦ç»§ç»çå¬è¿ä¸ªsocketçè¯ï¼éè¦å次æè¿ä¸ªsocketå å ¥å°EPOLLéåé
3. int epoll_wait(int epfd, struct epoll_event *events, int maxevents, int timeout);
çå¾ äºä»¶ç产çãåæ°events ç¨æ¥ä»å æ ¸å¾å°äºä»¶çéåï¼maxevents åä¹å æ ¸è¿ä¸ªevents æå¤å¤§ï¼è¿ä¸ªmaxevents çå¼ä¸è½å¤§äºå建epoll_create()æ¶çsizeï¼åæ°timeoutæ¯è¶ æ¶æ¶é´ï¼æ¯«ç§ï¼0ä¼ç«å³è¿åï¼-1å°ä¸ç¡®å®ï¼ä¹æ说æ³è¯´æ¯æ°¸ä¹ é»å¡ï¼ã该å½æ°è¿åéè¦å¤ççäºä»¶æ°ç®ï¼å¦è¿å0è¡¨ç¤ºå·²è¶ æ¶ã
4. EPOLLäºä»¶æ两ç§æ¨¡åï¼
Edge Triggered (ET) è¾¹ç¼è§¦å åªææ°æ®å°æ¥ï¼æ触åï¼ä¸ç®¡ç¼ååºä¸æ¯å¦è¿ææ°æ®ã
Level Triggered (LT) 水平触å åªè¦ææ°æ®é½ä¼è§¦åã
åå¦æè¿æ ·ä¸ä¸ªä¾åï¼
1. æ们已ç»æä¸ä¸ªç¨æ¥ä»ç®¡éä¸è¯»åæ°æ®çæ件å¥æ(RFD)æ·»å å°epollæ述符
2. è¿ä¸ªæ¶åä»ç®¡éçå¦ä¸ç«¯è¢«åå ¥äº2KBçæ°æ®
3. è°ç¨epoll_wait(2)ï¼å¹¶ä¸å®ä¼è¿åRFDï¼è¯´æå®å·²ç»åå¤å¥½è¯»åæä½
4. ç¶åæ们读åäº1KBçæ°æ®
5. è°ç¨epoll_wait(2)......
Edge Triggered å·¥ä½æ¨¡å¼ï¼
å¦ææ们å¨ç¬¬1æ¥å°RFDæ·»å å°epollæ述符çæ¶å使ç¨äºEPOLLETæ å¿ï¼é£ä¹å¨ç¬¬5æ¥è°ç¨epoll_wait(2)ä¹åå°æå¯è½ä¼æèµ·ï¼å 为å©ä½çæ°æ®è¿åå¨äºæ件çè¾å ¥ç¼å²åºå ï¼èä¸æ°æ®ååºç«¯è¿å¨çå¾ ä¸ä¸ªé对已ç»ååºæ°æ®çåé¦ä¿¡æ¯ãåªæå¨çè§çæ件å¥æä¸åçäºæ个äºä»¶çæ¶å ET å·¥ä½æ¨¡å¼æä¼æ±æ¥äºä»¶ãå æ¤å¨ç¬¬5æ¥çæ¶åï¼è°ç¨è å¯è½ä¼æ¾å¼çå¾ ä»å¨åå¨äºæ件è¾å ¥ç¼å²åºå çå©ä½æ°æ®ãå¨ä¸é¢çä¾åä¸ï¼ä¼æä¸ä¸ªäºä»¶äº§çå¨RFDå¥æä¸ï¼å 为å¨ç¬¬2æ¥æ§è¡äºä¸ä¸ªåæä½ï¼ç¶åï¼äºä»¶å°ä¼å¨ç¬¬3æ¥è¢«éæ¯ãå 为第4 æ¥ç读åæä½æ²¡æ读空æ件è¾å ¥ç¼å²åºå çæ°æ®ï¼å æ¤æ们å¨ç¬¬5 æ¥è°ç¨epoll_wait(2)å®æåï¼æ¯å¦æèµ·æ¯ä¸ç¡®å®çãepollå·¥ä½å¨ET模å¼çæ¶åï¼å¿ 须使ç¨éé»å¡å¥æ¥å£ï¼ä»¥é¿å ç±äºä¸ä¸ªæ件å¥æçé»å¡è¯»/é»å¡åæä½æå¤çå¤ä¸ªæ件æ述符çä»»å¡é¥¿æ»ãæ好以ä¸é¢çæ¹å¼è°ç¨ET模å¼çepollæ¥å£ï¼å¨åé¢ä¼ä»ç»é¿å å¯è½ç缺é·ã
i åºäºéé»å¡æ件å¥æ
ii åªæå½read(2)æè write(2)è¿åEAGAINæ¶æéè¦æèµ·ï¼çå¾ ãä½è¿å¹¶ä¸æ¯è¯´æ¯æ¬¡read()æ¶é½éè¦å¾ªç¯è¯»ï¼ç´å°è¯»å°äº§çä¸ä¸ªEAGAIN æ认为æ¤æ¬¡äºä»¶å¤çå®æï¼å½read()è¿åç读å°çæ°æ®é¿åº¦å°äºè¯·æ±çæ°æ®é¿åº¦æ¶ï¼å°±å¯ä»¥ç¡®å®æ¤æ¶ç¼å²ä¸å·²æ²¡ææ°æ®äºï¼ä¹å°±å¯ä»¥è®¤ä¸ºæ¤äºè¯»äºä»¶å·²å¤çå®æãLevel Triggered å·¥ä½æ¨¡å¼ç¸åçï¼ä»¥LTæ¹å¼è°ç¨epollæ¥å£çæ¶åï¼å®å°±ç¸å½äºä¸ä¸ªé度æ¯è¾å¿«çpoll(2)ï¼å¹¶ä¸æ 论åé¢çæ°æ®æ¯å¦è¢«ä½¿ç¨ï¼å æ¤ä»ä»¬å ·æåæ ·çèè½ãå 为å³ä½¿ä½¿ç¨ET模å¼çepollï¼å¨æ¶å°å¤ä¸ªchunk çæ°æ®çæ¶åä»ç¶ä¼äº§çå¤ä¸ªäºä»¶ãè°ç¨è å¯ä»¥è®¾å®EPOLLONESHOTæ å¿ï¼å¨ epoll_wait(2)æ¶å°äºä»¶åepollä¼ä¸äºä»¶å ³èçæ件å¥æä»epollæ述符ä¸ç¦æ¢æãå æ¤å½EPOLLONESHOT设å®åï¼ä½¿ç¨å¸¦æ EPOLL_CTL_MODæ å¿çepoll_ctl(2)å¤çæ件å¥æå°±æ为è°ç¨è å¿ é¡»ä½çäºæ ã
ç¶å详ç»è§£éET, LT:
LT(level triggered)æ¯ç¼ºççå·¥ä½æ¹å¼ï¼å¹¶ä¸åæ¶æ¯æblock åno-blocksocket.å¨è¿ç§åæ³ä¸ï¼å æ ¸åè¯ä½ ä¸ä¸ªæ件æ述符æ¯å¦å°±ç»ªäºï¼ç¶åä½ å¯ä»¥å¯¹è¿ä¸ªå°±ç»ªçfdè¿è¡IOæä½ãå¦æä½ ä¸ä½ä»»ä½æä½ï¼å æ ¸è¿æ¯ä¼ç»§ç»éç¥ä½ çï¼æ以ï¼è¿ç§æ¨¡å¼ç¼ç¨åºé误å¯è½æ§è¦å°ä¸ç¹ãä¼ ç»çselect/pollé½æ¯è¿ç§æ¨¡åç代表ï¼
ET(edge-triggered)æ¯é«éå·¥ä½æ¹å¼ï¼åªæ¯æno-block socketãå¨è¿ç§æ¨¡å¼ä¸ï¼å½æ述符ä»æªå°±ç»ªå为就绪æ¶ï¼å æ ¸éè¿epollåè¯ä½ ãç¶åå®ä¼åè®¾ä½ ç¥éæ件æ述符已ç»å°±ç»ªï¼å¹¶ä¸ä¸ä¼å为é£ä¸ªæ件æ述符åéæ´å¤ç就绪éç¥ï¼ç´å°ä½ åäºæäºæä½å¯¼è´é£ä¸ªæ件æ述符ä¸å为就绪ç¶æäº(æ¯å¦ï¼ä½ å¨åéï¼æ¥æ¶æè æ¥æ¶è¯·æ±ï¼æè åéæ¥æ¶çæ°æ®å°äºä¸å®éæ¶å¯¼è´äºä¸ä¸ªEWOULDBLOCK é误ï¼ãä½æ¯è¯·æ³¨æï¼å¦æä¸ç´ä¸å¯¹è¿ä¸ªfdä½IOæä½(ä»è导è´å®å次åææªå°±ç»ª)ï¼å æ ¸ä¸ä¼åéæ´å¤çéç¥(only once),ä¸è¿å¨TCPåè®®ä¸ï¼ET模å¼çå éæç¨ä»éè¦æ´å¤çbenchmark确认ï¼è¿å¥è¯ä¸ç解ï¼ã
å¨è®¸å¤æµè¯ä¸æ们ä¼çå°å¦æ没æ大éçidle -connection æè deadconnectionï¼epoll çæç并ä¸ä¼æ¯select/poll é«å¾å¤ï¼ä½æ¯å½æ们éå°å¤§éçidleconnection(ä¾å¦WAN ç¯å¢ä¸åå¨å¤§éçæ ¢éè¿æ¥)ï¼å°±ä¼åç°epoll çæç大大é«äºselect/pollãï¼æªæµè¯ï¼
å¦å¤ï¼å½ä½¿ç¨epollçET模åæ¥å·¥ä½æ¶ï¼å½äº§çäºä¸ä¸ªEPOLLINäºä»¶åï¼è¯»æ°æ®çæ¶åéè¦èèçæ¯å½recv()è¿åç大å°å¦æçäºè¯·æ±ç大å°ï¼é£ä¹å¾æå¯è½æ¯ç¼å²åºè¿ææ°æ®æªè¯»å®ï¼ä¹æå³ç该次äºä»¶è¿æ²¡æå¤çå®ï¼æ以è¿éè¦å次读åï¼
while(rs) {
buflen = recv(activeevents[i].data.fd, buf, sizeof(buf), 0);
if(buflen < 0) {
// ç±äºæ¯éé»å¡ç模å¼,æ以å½errno为EAGAINæ¶,表示å½åç¼å²åºå·²æ æ°æ®å¯è¯»
// å¨è¿éå°±å½ä½æ¯è¯¥æ¬¡äºä»¶å·²å¤çå¤.
if(errno == EAGAIN) {
break;
} else {
return;
}
} else if(buflen == 0) {
// è¿é表示对端çsocketå·²æ£å¸¸å ³é.
}
if(buflen == sizeof(buf)) {
rs = 1; // éè¦å次读å
} else {
rs = 0;
}
}
è¿æï¼åå¦åé端æµé大äºæ¥æ¶ç«¯çæµé(æææ¯epollæå¨çç¨åºè¯»æ¯è½¬åçsocketè¦å¿«),ç±äºæ¯éé»å¡çsocket,é£ä¹send()å½æ°è½ç¶è¿å,ä½å®é ç¼å²åºçæ°æ®å¹¶æªçæ£åç»æ¥æ¶ç«¯,è¿æ ·ä¸æç读ååï¼å½ç¼å²åºæ»¡åä¼äº§çEAGAINé误(åèman send),åæ¶,ä¸çä¼è¿æ¬¡è¯·æ±åéçæ°æ®.æ以,éè¦å°è£ socket_send()çå½æ°ç¨æ¥å¤çè¿ç§æ åµ,该å½æ°ä¼å°½éå°æ°æ®åå®åè¿åï¼è¿å-1 表示åºéãå¨socket_send()å é¨,å½åç¼å²å·²æ»¡(send()è¿å-1,ä¸errno为EAGAIN),é£ä¹ä¼çå¾ ååéè¯.è¿ç§æ¹å¼å¹¶ä¸å¾å®ç¾,å¨ç论ä¸å¯è½ä¼é¿æ¶é´çé»å¡å¨socket_send()å é¨,ä½æ没ææ´å¥½çåæ³.
ssize_t socket_send(int sockfd, const char* buffer, size_t buflen) {
ssize_t tmp;
size_t total = buflen;
const char *p = buffer;
while(1) {
tmp = send(sockfd, p, total, 0);
if(tmp < 0) {
// å½sendæ¶å°ä¿¡å·æ¶,å¯ä»¥ç»§ç»å,ä½è¿éè¿å-1.
if(errno == EINTR)
return -1;
// å½socketæ¯éé»å¡æ¶,å¦è¿åæ¤é误,表示åç¼å²éå已满,
// å¨è¿éå延æ¶ååéè¯.
if(errno == EAGAIN) {
usleep(1000);
continue;
}
return -1;
}
if((size_t)tmp == total)
return buflen;
total -= tmp;
p += tmp;
}
return tmp;
}
温馨提示:答案为网友推荐,仅供参考