我是靠谱客的博主 慈祥冰淇淋,这篇文章主要介绍EpollEpoll - IO多路复用怎么理解,现在分享给大家,希望可以做个参考。

目录

  • Epoll - IO多路复用
  • 怎么理解
    • 创建Epoll
    • 向EPOLL对象中添加、修改或者删除感兴趣的事件
    • 收集在epoll监控的事件中已经发生的事件
    • 完整代码

Epoll - IO多路复用

怎么理解

在这里插入图片描述

类比快递员寄快递,传统方式是快递员挨家挨户上楼敲门现,在改为用快递柜子的方式,比如丰巢类似,现在这里有两个集合。
1.住户所有人是一个集合。
2.丰巢是一个子集,比如今天要寄快递的住户。
epoll就是管理这两个集合。
epoll_create相当于一栋楼,聘请了一个快递员,创建一栋楼
epoll_ctl往楼里搬住户,它具备三个功能:
1.是往这栋楼搬一个住户进来。
2.一个用户搬出来。
3.比如一个用户从7楼搬到8楼
分别对应下面三种,增删改。
epoll_ctl(ADD,DEL,MOD)
epoll_wiat是快递员多久来丰巢取一次快递

创建Epoll

复制代码
1
2
int epoll_create(int size);

参数:
size:只要大于0即可,如果传一个<=0是不可用的
实际上,这里你传1或者10000区别是不大的,那为什么还需要这个参数呢?
早先版本的epoll他的队列大小是用size来定义的,也就是"“快递柜”"的大小,而后来不使用此参数的原因是其改为了链表存储(动态),保留此参数是为了保证代码的兼容.

创建完后还要准备一个东西 ----- epoll_event
这就好比快递员从快递柜拿快递走,不可能整个快递柜都搬走,这里就类比成一个袋子,或者一个小推车,用来装快递柜里的快递,这个我们就要定义大小了

复制代码
1
2
3
4
5
6
struct epoll_event event[设置大小POLL_SIZE] = {0}; //多大合适的问题? //假设快递柜有50个格子,你的推车只能装10个,那么跑5趟即可. //这里只是跑的次数多少而已,对数量没有要求,设置的大,跑的次数少,设置的小,跑的次数多 //而且这个小车大小是可变的,初始不要设置太小

结构原型

复制代码
1
2
3
4
5
6
7
8
9
10
11
12
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

向EPOLL对象中添加、修改或者删除感兴趣的事件

复制代码
1
2
3
4
5
6
7
8
9
10
11
int epoll_ctl(int epfd, int op, int fd, struct epoll_event *event); op取值:EPOLL_CTL_ADD 添加新的事件到epoll中 EPOLL_CTL_MOD 修改EPOLL中的事件 EPOLL_CTL_DEL 删除epoll中的事件 events取值: EPOLLIN 表示有数据可以读出(接受连接、关闭连接) EPOLLOUT 表示连接可以写入数据发送(向服务器发起连接,连接成功事件) EPOLLERR 表示对应的连接发生错误 EPOLLHUP 表示对应的连接被挂起

示例片段:

复制代码
1
2
3
4
5
6
7
struct epoll_event ev; ev.events = EPOLLIN; ev.data.fd = linstenfd; epoll_ctl(epfd, EPOLL_CTL_ADD, listenfd, &ev);

收集在epoll监控的事件中已经发生的事件

快递员去快递柜取出快递

复制代码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
int epoll_wait(int epfd, struct epoll_event * events, int maxevents, int timeout); epfd: epoll的描述符。 events:分配好的 epoll_event结构体数组,epoll将会把发生的事件复制到 events数组中 (events不可以是空指针,内核只负责把数据复制到这个 events数组中,不会去帮助我们在用户态中分配内存。内核这种做法效率很高)。 maxevents: 本次可以返回的最大事件数目,通常 maxevents参数与预分配的events数组的大小是相等的。 timeout: 表示在没有检测到事件发生时最多等待的时间(单位为毫秒), 如果timeout为0,立刻返回,不会等待。-1表示无限期阻塞

示例片段:

复制代码
1
2
3
4
5
6
7
8
while(1) { int nready = epoll_wait(epfd, events, POLL_SIZE, 5); //POLL_SIZE小车能装多少快递, 5毫秒去一趟 //nready返回事件个数 if(nready == -1)continue; }

完整代码

复制代码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
#include <errno.h> #include <netinet/in.h> #include <stdio.h> #include <stdlib.h> #include <string.h> #include <sys/socket.h> #include <sys/types.h> #include <unistd.h> #include <sys/poll.h> #include <sys/epoll.h> #include <pthread.h> #define MAXLNE 4096 #define POLL_SIZE 1024 //8m * 4G = 128 , 512 //C10k void *client_routine(void *arg) { // int connfd = *(int *)arg; char buff[MAXLNE]; while (1) { int n = recv(connfd, buff, MAXLNE, 0); if (n > 0) { buff[n] = ''; printf("recv msg from client: %sn", buff); send(connfd, buff, n, 0); } else if (n == 0) { close(connfd); break; } } return NULL; } int main(int argc, char **argv) { int listenfd, connfd, n; struct sockaddr_in servaddr; char buff[MAXLNE]; if ((listenfd = socket(AF_INET, SOCK_STREAM, 0)) == -1) { printf("create socket error: %s(errno: %d)n", strerror(errno), errno); return 0; } memset(&servaddr, 0, sizeof(servaddr)); servaddr.sin_family = AF_INET; servaddr.sin_addr.s_addr = htonl(INADDR_ANY); servaddr.sin_port = htons(9999); if (bind(listenfd, (struct sockaddr *)&servaddr, sizeof(servaddr)) == -1) { printf("bind socket error: %s(errno: %d)n", strerror(errno), errno); return 0; } if (listen(listenfd, 10) == -1) { printf("listen socket error: %s(errno: %d)n", strerror(errno), errno); return 0; } #if 0 struct sockaddr_in client; socklen_t len = sizeof(client); if ((connfd = accept(listenfd, (struct sockaddr *)&client, &len)) == -1) { printf("accept socket error: %s(errno: %d)n", strerror(errno), errno); return 0; } printf("========waiting for client's request========n"); while (1) { n = recv(connfd, buff, MAXLNE, 0); if (n > 0) { buff[n] = ''; printf("recv msg from client: %sn", buff); send(connfd, buff, n, 0); } else if (n == 0) { close(connfd); } //close(connfd); } #elif 0 printf("========waiting for client's request========n"); while (1) { struct sockaddr_in client; socklen_t len = sizeof(client); if ((connfd = accept(listenfd, (struct sockaddr *)&client, &len)) == -1) { printf("accept socket error: %s(errno: %d)n", strerror(errno), errno); return 0; } n = recv(connfd, buff, MAXLNE, 0); if (n > 0) { buff[n] = ''; printf("recv msg from client: %sn", buff); send(connfd, buff, n, 0); } else if (n == 0) { close(connfd); } //close(connfd); } #elif 0 while (1) { struct sockaddr_in client; socklen_t len = sizeof(client); if ((connfd = accept(listenfd, (struct sockaddr *)&client, &len)) == -1) { printf("accept socket error: %s(errno: %d)n", strerror(errno), errno); return 0; } pthread_t threadid; pthread_create(&threadid, NULL, client_routine, (void*)&connfd); } #elif 0 // fd_set rfds, rset, wfds, wset; FD_ZERO(&rfds); FD_SET(listenfd, &rfds); FD_ZERO(&wfds); int max_fd = listenfd; while (1) { rset = rfds; wset = wfds; int nready = select(max_fd+1, &rset, &wset, NULL, NULL); if (FD_ISSET(listenfd, &rset)) { // struct sockaddr_in client; socklen_t len = sizeof(client); if ((connfd = accept(listenfd, (struct sockaddr *)&client, &len)) == -1) { printf("accept socket error: %s(errno: %d)n", strerror(errno), errno); return 0; } FD_SET(connfd, &rfds); if (connfd > max_fd) max_fd = connfd; if (--nready == 0) continue; } int i = 0; for (i = listenfd+1;i <= max_fd;i ++) { if (FD_ISSET(i, &rset)) { // n = recv(i, buff, MAXLNE, 0); if (n > 0) { buff[n] = ''; printf("recv msg from client: %sn", buff); FD_SET(i, &wfds); //reactor //send(i, buff, n, 0); } else if (n == 0) { // FD_CLR(i, &rfds); //printf("disconnectn"); close(i); } if (--nready == 0) break; } else if (FD_ISSET(i, &wset)) { send(i, buff, n, 0); FD_SET(i, &rfds); } } } #elif 0 struct pollfd fds[POLL_SIZE] = {0}; fds[0].fd = listenfd; fds[0].events = POLLIN; int max_fd = listenfd; int i = 0; for (i = 1;i < POLL_SIZE;i ++) { fds[i].fd = -1; } while (1) { int nready = poll(fds, max_fd+1, -1); if (fds[0].revents & POLLIN) { struct sockaddr_in client; socklen_t len = sizeof(client); if ((connfd = accept(listenfd, (struct sockaddr *)&client, &len)) == -1) { printf("accept socket error: %s(errno: %d)n", strerror(errno), errno); return 0; } printf("accept n"); fds[connfd].fd = connfd; fds[connfd].events = POLLIN; if (connfd > max_fd) max_fd = connfd; if (--nready == 0) continue; } //int i = 0; for (i = listenfd+1;i <= max_fd;i ++) { if (fds[i].revents & POLLIN) { n = recv(i, buff, MAXLNE, 0); if (n > 0) { buff[n] = ''; printf("recv msg from client: %sn", buff); send(i, buff, n, 0); } else if (n == 0) { // fds[i].fd = -1; close(i); } if (--nready == 0) break; } } } #else //poll/select --> // epoll_create // epoll_ctl(ADD, DEL, MOD) // epoll_wait int epfd = epoll_create(1); //int size struct epoll_event events[POLL_SIZE] = {0}; struct epoll_event ev; ev.events = EPOLLIN; ev.data.fd = listenfd; epoll_ctl(epfd, EPOLL_CTL_ADD, listenfd, &ev); while (1) { int nready = epoll_wait(epfd, events, POLL_SIZE, 5); if (nready == -1) { continue; } int i = 0; for (i = 0;i < nready;i ++) { int clientfd = events[i].data.fd; if (clientfd == listenfd) { struct sockaddr_in client; socklen_t len = sizeof(client); if ((connfd = accept(listenfd, (struct sockaddr *)&client, &len)) == -1) { printf("accept socket error: %s(errno: %d)n", strerror(errno), errno); return 0; } printf("acceptn"); ev.events = EPOLLIN; ev.data.fd = connfd; epoll_ctl(epfd, EPOLL_CTL_ADD, connfd, &ev); } else if (events[i].events & EPOLLIN) { printf("recvn"); n = recv(clientfd, buff, MAXLNE, 0); if (n > 0) { buff[n] = ''; printf("recv msg from client: %sn", buff); send(clientfd, buff, n, 0); } else if (n == 0) { // ev.events = EPOLLIN; ev.data.fd = clientfd; epoll_ctl(epfd, EPOLL_CTL_DEL, clientfd, &ev); close(clientfd); } } } } #endif close(listenfd); return 0; }

最后

以上就是慈祥冰淇淋最近收集整理的关于EpollEpoll - IO多路复用怎么理解的全部内容,更多相关EpollEpoll内容请搜索靠谱客的其他文章。

本图文内容来源于网友提供,作为学习参考使用,或来自网络收集整理,版权属于原作者所有。
点赞(65)

评论列表共有 0 条评论

立即
投稿
返回
顶部