EPOLL使用注意

EPOLL使用注意

  (2007-05-25 09:52:25)
标签: 

epoll

 

et

 

epoll_ctl

 

epoll_ctl_add

 

epoll_ctl_mod

 

网络通讯

 

tcp

分类: 开发经验

接上篇文章,这段时间一直对使用EPOLL关联socket的网络通讯进行测试,功能测试就不用说了,网络上有很多实现例子,都可以参考;我主要集中在压力测试和稳定情况的分析,现有了自己的一点体会,特贴出来供大家批驳。
首先描述一下测试环境:Linux服务器,内核版本:2.6.9,g++版本3.4.6,EPOLL都使用ET模式。
第一个体会是关于监听套接字m_hListenSocket和epoll关联。一般的例子都是创建监听套接字和EPOLL描述苻后使用如下代码建立关联:
       struct epoll_event struEvent;
       struEvent.events = EPOLLIN | EPOLLET;
       struEvent.data.fd = m_hListenSocket;
       epoll_ctl(m_hEpoll, EPOLL_CTL_ADD, m_hListenSocket, &struEvent);
建立连接后,任何客户端和服务器监听端口建立连接的功能测试都是正常的,可以建立连接、收发数据等。但开启压力测试后发现了新问题,150个连接没间隔1秒和服务器建立连接,发现EPOLL只返回给我130个请求,并建立了130个连接;反复测试了多次,都是如此,那剩余的客户端请求那里去了?接着测试了300个连接,发现EPOLL只返回给我280个请求,也吃掉了20个请求;如果先建立150个连接,再一个一个的请求会发生什么呢?测试的情况是第131个请求不是151个请求,是被EPOLL吃掉的请求出来了;也就是说新请求可以把EPOLL未投递给我的消息顶出来,EPOLL一直保持着20个请求不返回,为什么会有这种现象呢?解决办法是什么呢?
带着这些疑问,反复进行了测试,发现使用EPOLL提供的LT模式,没有这种问题,但CPU消耗实在是太高了,不能接受。
测试了接收和发送数据了TCP套接字,由于每次发送数据后都使用如下代码,和epoll重新建立了关联,所以没有发生过EPOLL吃掉消息的问题。注意如不使用代码再次建立关联,则不能使用户socket持续发送数据。
       struct epoll_event struEvent;
       struEvent.events = EPOLLIN | EPOLLOUT | EPOLLET;
       struEvent.data.fd = hSocket;
       epoll_ctl(m_hEpoll, EPOLL_CTL_MOD, hSocket, &struEvent);
同时获得这个启发,是不是ET模式下,接受客户端请求建立连接时,EPOLL也要和监听套接字m_hListenSocket重新建立关联呢 ,随即增加了如下代码进行了测试:
     epoll_ctl(m_hEpoll, EPOLL_CTL_MOD, m_hListenSocket, &struEvent);
这下好了,无论是150个连接还是300个,EPOLL都可以完整的反馈给我了。看来这一步是必须的,但为什么EPOLL一定要吃掉20个请求呢,这点是我最不能理解呢?如果没有关联,那第2个请求或第3个就应当不返回了,真诚希望能有高手给予一个明确的答复。
### 回答1: `epoll` 函数是 Linux 系统中一个用于处理大量并发连接的 I/O 多路复用机制。它通过维护一个文件描述符集合来监测多个描述符的状态,以便在发生 I/O 事件时快速通知程序。 使用 `epoll` 的基本流程如下: 1. 创建 `epoll` 句柄:使用 `epoll_create` 或 `epoll_create1` 函数创建一个 `epoll` 句柄。 2. 注册文件描述符:使用 `epoll_ctl` 函数向 `epoll` 句柄中添加需要监测的文件描述符,并为每个文件描述符设置监测事件。 3. 进行等待:使用 `epoll_wait` 函数阻塞等待,直到有一个或多个文件描述符准备就绪。 4. 处理事件:当有文件描述符就绪时,处理相应的 I/O 事件。 5. 重复步骤 3 和 4,不断监测文件描述符的状态,处理 I/O 事件。 常见的使用方式是:创建一个线程,在线程中调用 `epoll_wait` 函数,当有文件描述符就绪时通过回调函数处理相应的 I/O 事件。 ### 回答2: epoll是Linux提供的一种高效的I/O事件通知模型。使用epoll函数需要经过以下几个步骤: 1. 创建一个epoll实例对象,可以通过调用epoll_create函数来创建,它会返回一个文件描述符。 2. 使用epoll_ctl函数将需要监听的文件描述符添加到epoll实例对象中,指定感兴趣的事件类型(如读、写、边缘触发等)。 3. 调用epoll_wait函数等待事件的发生,该函数会阻塞程序运行,直到有感兴趣的事件发生。 4. 当epoll_wait返回时,可以通过遍历就绪的事件列表来处理每个事件。 - 可以通过events[i].events来获取事件类型,如EPOLLIN表示可读事件,EPOLLOUT表示可写事件。 - 可以通过events[i].data.fd获取文件描述符,进行相应的读或写操作。 - 根据需要,还可以使用epoll_ctl函数来动态地修改监听的事件类型或删除特定的文件描述符。 5. 处理完就绪的事件后,可以继续调用epoll_wait等待更多的事件。 需要注意的是,epoll函数的使用需要在Linux环境下,且需要对事件的读写操作做相应的处理,以使程序能够根据事件的发生来及时地做出响应。同时,需要注意合理使用epoll实例对象的大小和调整内核的最大用户限制来提高性能和稳定性。另外,尽量避免频繁地添加和删除文件描述符以减少系统开销。 ### 回答3: epoll(事件驱动的 I/O多路复用机制)是一种高效的I/O多路复用技术,用于在 Linux 系统上处理大量的并发连接。 使用epoll函数的步骤如下: 1. 创建一个epoll实例。通过调用epoll_create函数创建一个epoll实例,它会返回一个文件描述符,用于操作epoll实例。 2. 向epoll实例中添加感兴趣的事件。通过调用epoll_ctl函数,向epoll实例中添加需要监听的事件,例如读事件或写事件,并将相应的文件描述符加入到epoll实例中进行管理。 3. 等待事件的发生。通过调用epoll_wait函数,等待事件的发生。该函数会阻塞当前线程,直到有感兴趣的事件发生,并将发生的事件以数组的形式返回,同时还可以设置超时时间。 4. 处理事件。根据返回的事件数组,对每个事件进行处理。根据事件的类型,可以进行读操作或写操作,也可以关闭连接等。 在具体使用epoll函数时,需要注意以下几点: 1. epoll事件的处理顺序不确定,因此需要对每个事件进行逐个处理,以确保所有事件都能得到处理。 2. 每个事件只能处理一次,否则会造成重复处理的问题。在处理完一个事件后,需要重新添加该事件到epoll实例中。 3. 需要及时释放不再使用epoll实例和文件描述符,以避免资源泄漏。 总的来说,epoll函数的使用需要创建epoll实例、添加事件、等待事件、处理事件这四个步骤,并且需要注意事件处理的顺序和及时释放资源。通过合理地使用epoll函数,可以有效地处理大量的并发连接,提高系统的性能和并发度。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值