当Epoll监听多个FD时,一直很好奇如果多个FD同时有事件触发,它是如何来进行调度的,调度的顺序是否和事件触发的顺序有关系?
借助简单的代码来分析一下:
代码原理较简单:
1. 主线程中创建两个eventfd描述符,加入epoll
2. 主线程在epoll_wait前,先在子线程中循环写入10次,调eventfd_write
3. 主线程进入epoll_wait,进行事件调度,读eventfd
结论:与调度顺序没有关系,结果可以看到fd1和fd2的事件是交替被处理到的
1 #include <sys/eventfd.h> 2 #include <unistd.h> 3 #include <stdlib.h> 4 #include <stdio.h> 5 #include <stdint.h> 6 #include <sys/epoll.h> 7 #include <string.h> 8 #include <pthread.h> 9 10 int g_iEvtfd1 = -1; 11 int g_iEvtfd2 = -1; 12 13 void *eventfd_child_Task(void *pArg) 14 { 15 uint64_t uiWrite = 1; 16 int i = 0; 17 18 for(i=0;i<10;i++) 19 { 20 eventfd_write(g_iEvtfd1, uiWrite); 21 } 22 23 for(i=0;i<10;i++) 24 { 25 eventfd_write(g_iEvtfd2, uiWrite); 26 } 27 28 printf("The child task is done! "); 29 return; 30 } 31 32 int main(int argc, char**argv[]) 33 { 34 int iEvtfd1, iEvtfd2, j; 35 uint64_t uiWrite = 1; 36 uint64_t uiRead; 37 ssize_t s; 38 int iEpfd; 39 struct epoll_event stEvent; 40 int iRet = 0; 41 struct epoll_event stEpEvent; 42 pthread_t stWthread; 43 44 iEpfd = epoll_create(1); 45 if (-1 == iEpfd) 46 { 47 printf("Create epoll failed. "); 48 return 0; 49 } 50 51 iEvtfd1 = eventfd(0,EFD_SEMAPHORE); 52 if (-1 == iEvtfd1) 53 { 54 printf("failed to create eventfd1 "); 55 return 0; 56 } 57 g_iEvtfd1 = iEvtfd1; 58 59 iEvtfd2 = eventfd(0,EFD_SEMAPHORE); 60 if (-1 == iEvtfd2) 61 { 62 printf("failed to create eventfd2 "); 63 return 0; 64 } 65 66 g_iEvtfd2 = iEvtfd2; 67 68 memset(&stEvent, 0, sizeof(struct epoll_event)); 69 stEvent.events = (unsigned long) EPOLLIN; 70 stEvent.data.fd = g_iEvtfd1; 71 iRet = epoll_ctl(iEpfd, EPOLL_CTL_ADD, g_iEvtfd1, &stEvent); 72 if (0 != iRet) 73 { 74 printf("failed to add g_iEvtfd1 to epoll "); 75 close(g_iEvtfd1); 76 close(g_iEvtfd2); 77 close(iEpfd); 78 return 0; 79 } 80 81 memset(&stEvent, 0, sizeof(struct epoll_event)); 82 stEvent.events = (unsigned long) EPOLLIN; 83 stEvent.data.fd = g_iEvtfd2; 84 iRet = epoll_ctl(iEpfd, EPOLL_CTL_ADD, g_iEvtfd2, &stEvent); 85 if (0 != iRet) 86 { 87 printf("failed to add g_iEvtfd2 to epoll "); 88 close(g_iEvtfd1); 89 close(g_iEvtfd2); 90 close(iEpfd); 91 return 0; 92 } 93 94 iRet = pthread_create(&stWthread, NULL, eventfd_child_Task, NULL); 95 if (0 != iRet) 96 { 97 close(g_iEvtfd1); 98 close(g_iEvtfd2); 99 close(iEpfd); 100 return; 101 } 102 103 for(;;) 104 { 105 sleep(2); 106 iRet = epoll_wait(iEpfd, &stEpEvent, 1, -1); 107 if (iRet > 0) 108 { 109 printf("epoll_wait return %d. ", iRet); 110 if(stEpEvent.data.fd == g_iEvtfd1) 111 { 112 printf("g_iEvtfd1 event "); 113 s = eventfd_read(g_iEvtfd1, &uiRead); 114 if (s != 0) 115 { 116 printf("read g_iEvtfd1 failed "); 117 break; 118 } 119 printf("Read %llu (0x%llx) from g_iEvtfd1 ", uiRead, uiRead); 120 } 121 else if (stEpEvent.data.fd == g_iEvtfd2) 122 { 123 printf("g_iEvtfd2 evnet "); 124 s = eventfd_read(g_iEvtfd2, &uiRead); 125 if (s != 0) 126 { 127 printf("read g_iEvtfd2 failed "); 128 break; 129 } 130 printf("Read %llu (0x%llx) from g_iEvtfd2 ", uiRead, uiRead); 131 } 132 else{ 133 printf("epoll wait error!"); 134 } 135 } 136 } 137 138 close(g_iEvtfd1); 139 close(g_iEvtfd2); 140 close(iEpfd); 141 return 0; 142 }