基于EPOLL机制的Linux网络服务器设计与实现 下载本文

内容发布更新时间 : 2024/6/26 16:08:16星期一 下面是文章的全部内容请认真阅读。

龙源期刊网 http://www.qikan.com.cn

基于EPOLL机制的Linux网络服务器设计与实现

作者:何凯

来源:《电子技术与软件工程》2016年第02期

摘 要

笔者在开发一款Linux网络服务器时,经过对多种机制的比较,发现EPOLL机制效率最高,该机制可以满足并发处理海量网络连接的要求,非常适合高性能服务器的设计要求。因此笔者对EPOLL机制进行了深入的研究,并且设计了一款基于EPOLL机制的高效的Linux网络服务器。在实际应用中,该服务器有着稳定、高效的特点。 【关键词】EPOLL Linux服务器 1 引言

笔者在实际工作中,需要开发一款基于Linux的高性能网络服务器,该服务器与前端的多种嵌入式设备通过有线网络或者无线网络连接。在对Linux网络编程技术分析后,最终选择了EPOLL机制。在经过几个月的调试、改进之后,服务器可以准确、稳定、高效的工作。在模拟测试中,该服务器可以稳定的连接与控制前端10万个设备。取得了良好的效果。 2 Linux中I/O多路复用技术分析

Linux上的I/O多路复用技术主要有select模型、poll模型和epoll模型。

select模型最大的缺点是最大并发数限制,因为一个进程所打开的socket FD(文件描述符)是有限制的,默认是1024,因此select模型的最大并发数就被限制了。当然,我们可以通过修改系统参数增大最大并发数,然而由于select的每次调用都会线性扫描全部的socket FD集合。当socket FD增大时,会导致服务器效率线性下降。

poll模型基本上和select在效率上是一样的,select的问题在poll模型中也没有被解决。 epoll模型是目前比较优秀的I/O多路复用模型,首先,epoll没有最大并发连接的限制,上限是整个系统最大可以打开的socket FD数目,这个数远大于2048,一般这个数目和系统内存关系很大,1G内存的机器的最大socket FD数目可以达到10万左右。其次,epoll最大的优点在于它只关心活跃的连接,而跟连接总数无关。因此在实际的网络环境中,epoll的效率会远高于select和poll。

龙源期刊网 http://www.qikan.com.cn

epoll相关的系统调用有:epoll_create, epoll_ctl和epoll_wait。其中epoll_create用来创建一个epoll文件描述符,epoll_ctl用来添加/修改/删除需要侦听的文件描述符及其事件,epoll_wait接收发生在被侦听的描述符上的,用户感兴趣的IO事件。epoll文件描述符用完后,直接用close关闭即可,非常方便。事实上,任何被侦听的文件符只要其被关闭,那么它也会自动从被侦听的文件描述符集合中删除,很是智能。 3 框架设计与系统实现 3.1 系统设计

整个系统分为三个部分:前端探测设备、网络服务器、上位机。

该网络服务器用于连接、监控和控制前端多种嵌入式探测设备,这些探测设备分布于广阔的空间范围,并通过有线网络或者无线网络与网络服务器相连。

网络服务器设计是本文的核心。网络服务器向下连接大量的探测设备,向上连接上位机。网络服务器的框架如图1所示。

多种前端嵌入式探测设备用于探测所在位置的温度、湿度、风速,以及其他意外突发情况,这些嵌入式设备将探测到的数据,以某种协议格式发送给网络服务器,可能是通过有线网络,也有可能通过无线网络。这些数据在网络服务器上存储并转发给上位机显示处理。 探测设备与网络服务器之间,用心跳帧维护链路。有的探测设备会主动发送心跳帧给服务器,有些探测设备则需要网络服务器发送心跳帧询问。对方收到心跳帧后,都给予应答帧。 3.2 服务器实现

(1)将服务器进程设置成实时进程 struct sched_param p; p.sched_priority = 9;

sched_setscheduler(0,SCHED_RR,&p);

(2)设置服务器时钟,只负责计时,其他事情不做,方式是记录流逝的秒数。使用全局变量ec,必须设置成原子的。在用sigaction函数登记的信号处理函数中可以做的处理是被严格限定的,所以变量ec必须是“volatile sig_atomic_t”类型的全局变量。代码如下: static volatile sig_atomic_t ec = 0;

龙源期刊网 http://www.qikan.com.cn

static void sig1sec_handler(int sig) { ++ec; }

下面代码,在主程序中设置并启动定时器,设定每一秒钟触发一次信号,该定时器信号导致函数sig1sec_handler的执行,该函数使得全局变量ec自增一。 signal(SIGALRM, &sig1sec_handler); struct itimerval t; t.it_interval.tv_sec = 1; t.it_interval.tv_usec = 0; t.it_value = t.it_interval;

setitimer(ITIMER_REAL, &t, NULL);

(3)设置进程的最大打开文件限制,相当于设置进程能够管理的TCP链接数量。设置数量限制为10万。 int cn = 100000; struct rlimit rlim, new;

new.rlim_cur = new.rlim_max = cn;

while (setrlimit(RLIMIT_NOFILE, &new)!=0) { cn -= 1000;

new.rlim_cur = new.rlim_max = cn; }

(4)捕获SIGPIPE信号。如果向收到RST的TCP链路写入数据,进程会收到SIGPIPE信号而终止进程,SIGPIPE信号的缺省处理方式就是终止进程,现在改成忽略处理。