C++面经总结
-
epoll 与 select/pool
epoll是Linux内核为处理大批量文件描述符而作了改进的poll,是多路复用IO接口select/poll的增强版本。
特点:获取事件时,无须遍历整个被侦听的描述符集,只需遍历被内核IO事件异步唤醒而加入Ready队列的描述符集合。同时支持水平出发(LT)与边沿出发(ET);
优点:1. 能显著提高程序在大量并发连接中只有少量活跃的情况下的系统CPU利用率; 2. 所支持的FD上限是最大可以打开文件的数目(与系统内存有关); 3. IO效率不随FD数目增加而线性下降。传统的select/poll每次调用都会线性扫描全部的集合,导致效率呈线性下降,而epoll是根据每个fd上面的callback函数实现。
系统调用:
epoll_create, epoll_ctl和epoll_wait(epoll_pwait)
- 包含头文件#include<sys/epoll.h>
-
创建一个epoll句柄
int epfd = epoll_create(POOL_SIZE);
-
设置事件监听
nfds = epoll_wait(epfd, events, maxevents, -1);
示例代码:
|
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 |
int epfd = epoll_create(POLL_SIZE); struct epoll_event ev; struct epoll_event *events = NULL; nfds = epoll_wait(epfd, events, 20, 500); { for (n = 0; n < nfds; ++n) { if (events[n].data.fd == listener) { //如果是主socket的事件的话,则表示 //有新连接进入了,进行新连接的处理。 client = accept(listener, (structsockaddr *)&local, &addrlen); if (client < 0) { perror("accept"); continue; } setnonblocking(client); //将新连接置于非阻塞模式 ev.events = EPOLLIN | EPOLLET; //并且将新连接也加入EPOLL的监听队列。 //注意,这里的参数EPOLLIN|EPOLLET并没有设置对写socket的监听, //如果有写操作的话,这个时候epoll是不会返回事件的,如果要对写操作 //也监听的话,应该是EPOLLIN|EPOLLOUT|EPOLLET ev.data.fd = client; if (epoll_ctl(epfd, EPOLL_CTL_ADD, client, &ev) < 0) { //设置好event之后,将这个新的event通过epoll_ctl加入到epoll的监听队列里面, //这里用EPOLL_CTL_ADD来加一个新的epoll事件,通过EPOLL_CTL_DEL来减少一个 //epoll事件,通过EPOLL_CTL_MOD来改变一个事件的监听方式。 fprintf(stderr, "epollsetinsertionerror:fd=%d", client); return -1; } } else if(event[n].events & EPOLLIN) { //如果是已经连接的用户,并且收到数据, //那么进行读入 int sockfd_r; if ((sockfd_r = event[n].data.fd) < 0) continue; read(sockfd_r, buffer, MAXSIZE); //修改sockfd_r上要处理的事件为EPOLLOUT ev.data.fd = sockfd_r; ev.events = EPOLLOUT | EPOLLET; epoll_ctl(epfd, EPOLL_CTL_MOD, sockfd_r, &ev) } else if(event[n].events & EPOLLOUT) { //如果有数据发送 int sockfd_w = events[n].data.fd; write(sockfd_w, buffer, sizeof(buffer)); //修改sockfd_w上要处理的事件为EPOLLIN ev.data.fd = sockfd_w; ev.events = EPOLLIN | EPOLLET; epoll_ctl(epfd, EPOLL_CTL_MOD, sockfd_w, &ev) } do_use_fd(events[n].data.fd); } } |
浙公网安备 33010602011771号