epoll-linux提高并发服务器效率
来源:互联网 发布:监控安装设计软件 编辑:程序博客网 时间:2024/05/20 11:26
在大家苦苦的为在线人数的增长而导致的系统资源吃紧上的问题正在发愁的时候,Linux 2.6内核中提供的System Epoll为我们提供了一套完美的解决方案。传统的select以及poll的效率会因为在线人数的线形递增而导致呈二次乃至三次方的下降,这些直接导致了网络服务器可以支持的人数有了个比较明显的限制。
自从Linux提供了/dev/epoll的设备以及后来2.6内核中对/dev/epoll设备的访问的封装(System Epoll)之后,这种现象得到了大大的缓解,如果说几个月前,大家还对epoll不熟悉,那么现在来说的话,epoll的应用已经得到了大范围的普及。
那么究竟如何来使用epoll呢?其实非常简单。
通过在包含一个头文件#include <sys/epoll.h>以及几个简单的API将可以大大的提高你的网络服务器的支持人数。
首先通过epoll_create(int maxfds)来创建一个epoll的句柄,其中maxfds为你epoll所支持的最大句柄数。这个函数会返回一个新的epoll句柄,之后的所有操作将通过这个句柄来进行操作。在用完之后,记得用close()来关闭这个创建出来的epoll句柄。
之后在你的网络主循环里面,每一帧的调用epoll_wait(int epfd, epoll_event events, int max events, int timeout)来查询所有的网络接口,看哪一个可以读,哪一个可以写了。基本的语法为:
1
nfds = epoll_wait(kdpfd, events, maxevents, -1);
其中kdpfd为用epoll_create创建之后的句柄,events是一个epoll_event*的指针,当epoll_wait这个函数操作成功之后,epoll_events里面将储存所有的读写事件。max_events是当前需要监听的所有socket句柄数。最后一个timeout是epoll_wait的超时,为0的时候表示马上返回,为-1的时候表示一直等下去,直到有事件范围,为任意正整数的时候表示等这么长的时间,如果一直没有事件,则返回。一般如果网络主循环是单独的线程的话,可以用-1来等,这样可以保证一些效率,如果是和主逻辑在同一个线程的话,则可以用0来保证主循环的效率。
epoll_wait范围之后应该是一个循环,遍历所有的事件:
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
for
(n = 0; n < nfds; ++n) {
if
(events[n].data.fd == listener) {
// 如果是主socket的事件的话,则表示
// 有新连接进入了,进行新连接的处理。
client = accept(listener, (
struct
sockaddr *) &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(kdpfd, EPOLL_CTL_ADD, client, &ev) < 0) {
// 设置好event之后,将这个新的event通过epoll_ctl加入到epoll的监听队列里面,
// 这里用EPOLL_CTL_ADD来加一个新的epoll事件,通过EPOLL_CTL_DEL来减少一个
// epoll事件,通过EPOLL_CTL_MOD来改变一个事件的监听方式。
fprintf
(stderr, "epoll set insertion error: fd=%d0, 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_r, &ev)
}
do_use_fd(events[n].data.fd);
}
对,epoll的操作就这么简单,总共不过4个API:epoll_create, epoll_ctl, epoll_wait和close。
- epoll-linux提高并发服务器效率
- Linux Epoll并发服务器开发
- C++ linux epoll并发服务器模型初探
- Linux服务器如何提高用户搜索效率
- 并发服务器之epoll
- epoll并发服务器
- 并发服务器epoll
- linux并发服务器中epoll+多线程分别怎么理解
- epoll+socket实现 socket并发 linux服务器 (c)
- epoll+socket实现并发服务器 Linux C(版本一)
- Epoll实现服务器高并发
- epoll实现服务器高并发
- 修改Linux内核参数提高服务器并发能力
- linux服务器编程--EPOLL
- linux下epoll服务器
- 【Linux】epoll 服务器
- IO复用(Reactor模式和Preactor模式)——用epoll来提高服务器并发能力
- 提高内存池的并发效率
- 大道PHP+LAMP+ZEND+开源框架整合开发与实战|pdf电子书(100m)
- Linux shell编程 13 ---- 子Shell与进程处理
- Ubuntu下利用scp在虚拟机和主机之间传输文件
- Django 1.5.4 专题23 Celery RabbitMQ
- 写博客好习惯的开始
- epoll-linux提高并发服务器效率
- MySQL增删改查
- apt-get下载安装本地包
- Java反编译工具Jad及插件JadClipse配置
- 字符集
- kernel BUG at mm/slab.c
- Apache启动不了,httpd: apr_sockaddr_info_get() failed for apache 启动问题
- 【LeetCode】Remove Nth Node From End of List
- samba服务配置时常见问题