1. 同select比较
对于select,linux/posix_types.h头文件有这样的宏:#define __FD_SETSIZE 1024;
select能监听的最大fd数量,在内核编译的时候就确定了的。若想加大fd的数量,需要调整编译参数,重新编译内核。
epoll_wait直接返回被触发的fd或对应的一块buffer,不需要遍历所有的fd。
epoll的实现中,用户空间跟内核空间共享内存(mmap),避免拷贝。
2. 基本的数据结构
typedef union epoll_data { //注意是union
void *ptr;
int fd;
uint32_t u32;
uint64_t u64;
} epoll_data_t;
struct epoll_event {
uint32_t events; /* Epoll events */
epoll_data_t data; /* User data variable */
};
3. 基本操作
3.1 加入到epoll监控
struct epoll_event ee;
ee.events = EPOLLIN|EPOLLOUT|EPOLLET; //不设置EPOLLET的话,为LT模式
ee.data.ptr = (void *) buffer;//传入buffer地址
epoll_ctl(epfd, EPOLL_CTL_ADD, socketfd, &ee);
3.2 从epoll监控中删除
struct epoll_event ee;
ee.events = 0;
ee.data.ptr = NULL;
epoll_ctl(epfd, EPOLL_CTL_DEL, socketfd, &ee);
3.3 等待事件的触发
for (;;){
nfds = epoll_wait(epollfd, events, MAX_EVENTS, -1);
if (nfds == -1){
if (errno == EINTR)
continue; // 中断
perror("epoll_pwait");
exit (EXIT_FAILURE);
}
for (n = 0; n < nfds; ++n){
// events[n].events; //是什么事件 EPOLLIN/EPOLLOUT/EPOLLERR/EPOLLPRI
// events[n].data.fd;//被触发的fd(在epoll_ctrl时传入的)
// events[n].data.ptr;//跟fd相关联的buffer(在epoll_ctrl时传入的)
if( events[n].events & EPOLLIN ) { }
else if( events[n].events & EPOLLOUT ) { }
else if( events[n].events & EPOLLERR ) { }
else {}
}
}
4. 读和写
epoll有2种模式, 水平触发(LT)&边缘触发(ET)。
4.1 LT模式下的读和写
读:若接收缓冲区中有数据,就会一直触发EPOLLIN。所以不用担心是否读干净缓冲区中的数据,若没有读完的话,EPOLL会一直被触发。
写:若发送缓冲区中还有空间的话,会一直触发EPOLLOUT(只有在发送缓冲区满的时候,才不会被触发)。所以这个很烦,本来没有数据需要发送,但EPOLLOUT仍然被触发。解决方法:
(1)epoll_ctl(, EPOLL_CTL_ADD, fd),将该fd加入到epoll中;
(2)该fd的EPOLLOUT被触发,发送数据(一般在回调函数中完成);
(3)epoll_ctl(epfd, EPOLL_CTL_DEL, fd),将该fd移出epoll。加入又移出的,很麻烦,又有开销。若数据比较少的时候,直接调用send发送好了。
4.2 ET模式下的读和写
ET模式下,是不能用阻塞式的函数的。
读:fd由不可读->可读(接收缓冲区没有数据->有数据)时,才会触发EPOLLIN。若没有读干净,read返回,缓冲区仍然有数据时, 不会再次触发。
n=read(fd, buf, buf_size);
if(n<0){
if (errno == EAGAIN)
continue;
else
return -1; //errno, should close the fd
}
else if(n < buf_size){
// 读完了缓冲区中的数据,可以返回
return n;
}
else if(n == buf_size){
// 缓冲区中可能还有数据,继续读
continue;
}
写:fd由不可写->可写(发送缓冲区满->有空间)时,才会触发EPOLLOUT。
5. 一个异步模型
(1)将要监控的fd加入到epoll的监控中,每一个fd对应一个事件处理类(EventHanlder),当fd被触发时,处理类中的相关函数被调用。
(2)用epoll可以实现定时器。依赖于epoll_wait的超时机制。该定时器存在
误差。
6. 代码
-
#pragma once
-
-
#include <time.h>
-
#include <map>
-
#include <sys/time.h>
-
#include <fcntl.h>
-
#include "min_heap.h"
-
-
class FDEventHanderBase;
-
class FDEventHanderSet;
-
class TimerEventHanderBase;
-
-
class NonCopyable
-
{
-
protected:
-
NonCopyable() {
-
}
-
virtual ~NonCopyable() {
-
}
-
private:
-
NonCopyable(const NonCopyable &); //禁止拷贝
-
const NonCopyable & operator=(const NonCopyable &); //禁止赋值
-
};
-
-
class Reactor: public NonCopyable
-
{
-
public:
-
Reactor() {
-
}
-
-
virtual ~Reactor() {
-
}
-
-
virtual bool Init() = 0;
-
virtual bool Run() = 0;
-
virtual bool Stop() = 0;
-
virtual int RegisterReadEvent(FDEventHanderBase* pBase) = 0;
-
virtual int RegisterWriteEvent(FDEventHanderBase* pBase) = 0;
-
virtual int UnRegisterReadEvent(FDEventHanderBase* pBase) = 0;
-
virtual int UnRegisterWriteEvent(FDEventHanderBase* pBase) = 0;
-
virtual int RegisterTimer(TimerEventHanderBase* pBase) = 0;
-
virtual int UnRegisterTimer(TimerEventHanderBase* pBase) = 0;
-
};
-
/* **********************************
-
* 处理FD类的基类
-
* 当该fd被触发时,调用处理函数来进行处理
-
* ***********************************/
-
class FDEventHanderBase: public NonCopyable
-
{
-
public:
-
FDEventHanderBase(int fd, Reactor* pReactor) :
-
m_fd(fd), m_pReactor(pReactor)
-
{
-
}
-
virtual ~FDEventHanderBase() {
-
}
-
// 读被触发时,调用该函数
-
virtual void OnFDRead() = 0;
-
// 写被触发时,调用该函数
-
virtual void OnFDWrite() = 0;
-
// 关闭fd
-
virtual void Close() = 0;
-
// 注册读事件
-
int RegisterReadEvent();
-
// 注册写事件
-
int RegisterWriteEvent();
-
// 注销读事件
-
int UnRegisterReadEvent();
-
// 注销写事件
-
int UnRegisterWriteEvent();
-
int GetFD() const;
-
void SetFD(int fd);
-
// 设置非阻塞,返回0,success.
-
int SetNonBlock(int fd, bool bNonBlock = true);
-
protected:
-
int m_fd;//该handler所对应的fd.
-
Reactor* m_pReactor;
-
};
-
/* **********************************
-
* 处理timer类的基类
-
* 当timer被触发时,调用该类的函数
-
* **********************************/
-
class TimerEventHanderBase: public NonCopyable
-
{
-
public:
-
TimerEventHanderBase(Reactor* reactor) :
-
m_pReactor(reactor), m_bRestart(false)
-
{
-
timerclear(&m_interval);
-
timerclear(&m_endtime);
-
}
-
virtual ~TimerEventHanderBase() {
-
}
-
virtual void OnTimeOut() = 0;
-
// 注册定时器,@msec,多长时间响一次,单位:毫秒
-
// 由于epoll精度的限制,这个地方,精度只能达到 毫秒,但不是准确
-
int RegisterTimer(unsigned int msec /*ms*/, bool restart = false);
-
int UnRegisterTimer();
-
int RegisterTimerAgain();
-
// 获取结束时间
-
const timeval& GetEndTime() const {
-
return m_endtime;
-
}
-
// 该定时器是否需要重启
-
bool IsRestart() const {
-
return m_bRestart;
-
}
-
protected:
-
Reactor* m_pReactor;
-
timeval m_interval;// 时间间隔
-
timeval m_endtime; // 定时器到期时间
-
bool m_bRestart;// 是否自动重启
-
};
-
-
/* **********************************
-
* 处理类的集合
-
* 有个对应关系 -- fd -- 处理函数 -- read/write.
-
* *********************************/
-
class EventHanderSet
-
{
-
public:
-
// 增加fd事件, @type : EPOLLIN, EPOLLOUT,
-
void AddFDEventHandler(FDEventHanderBase* pHandler, int type);
-
// @type : EPOLLIN, EPOLLOUT
-
void DelFDEventHandler(int fd, int type);
-
// 根据fd,找到 FDEventHanderBase,及type.
-
FDEventHanderBase* GetFDEventHandler(int fd, int& type);
-
public:
-
void AddTimerEventHandler(TimerEventHanderBase* pHandler);
-
void DelTimerEventHandler(TimerEventHanderBase* pHandler);
-
void ScanTimer();
-
private:
-
struct FDHandler
-
{
-
int type; //EPOLLIN, EPOLLOUT
-
FDEventHanderBase* pHandler;
-
};
-
std::map<int, FDHandler> m_fdmap; // fd -- type -- handler
-
-
// 用于保存timer,在同一时刻,可能有多个handler.
-
MinHeap<std::pair<long int, long int> > m_timerMinHeap;
-
std::multimap<std::pair<long int, long int>, TimerEventHanderBase*>
-
m_timerMultiMap;
-
};
-
-
//////////// LT epoll /////////////////
-
class LTReactor: public Reactor
-
{
-
public:
-
LTReactor();
-
virtual ~LTReactor();
-
-
bool Init();
-
bool Run();
-
bool Stop();
-
//注册读事件
-
int RegisterReadEvent(FDEventHanderBase* pBase);
-
//注册写事件
-
int RegisterWriteEvent(FDEventHanderBase* pBase);
-
-
int UnRegisterReadEvent(FDEventHanderBase* pBase);
-
int UnRegisterWriteEvent(FDEventHanderBase* pBase);
-
int UnRegisterAllEvent(FDEventHanderBase* pBase);
-
// 注册定时器
-
int RegisterTimer(TimerEventHanderBase* pBase);
-
int UnRegisterTimer(TimerEventHanderBase* pBase);
-
private:
-
void ScanTimer();
-
private:
-
int m_epfd; //epoll's fd
-
bool m_bRunning;
-
timeval m_stoptime; //停止时间
-
EventHanderSet m_handlerSet;
-
};
-
#include "reactor.h"
-
#include <sys/epoll.h>
-
#include <errno.h>
-
#include <iostream>
-
#include <string.h>
-
#include <stdio.h>
-
-
/////////////////////////////////////////////////////////
-
#define MAX_EPOLL_SIZE 1024
-
#define MAX_EPOLL_EVENTS_SIZE 128
-
-
LTReactor::LTReactor() :
-
m_epfd(-1), m_bRunning(false)
-
{
-
}
-
-
LTReactor::~LTReactor() {
-
}
-
-
bool LTReactor::Init() {
-
m_epfd = epoll_create(MAX_EPOLL_SIZE);
-
if (m_epfd == -1)
-
{
-
std::cout << "epoll_create error: " << strerror(errno) << std::endl;
-
return false;
-
}
-
-
m_bRunning = true;
-
return true;
-
}
-
-
bool LTReactor::Run() {
-
struct epoll_event events[MAX_EPOLL_EVENTS_SIZE];
-
int nfds = 0; //返回被触发的事件的个数
-
while (true)
-
{
-
// 超时时间,若m_bRunning,立即返回;否则100ms,即0.1s. 实际上,epoll_wait,只能够精确到毫秒(1/1000)
-
nfds = epoll_wait(m_epfd, events, sizeof(events) / sizeof(events[0]),
-
m_bRunning ? 100 : 1);
-
// 要停止epoll.
-
if (m_bRunning == false)
-
{
-
timeval now;
-
gettimeofday(&now, NULL); //获取当前时间
-
if (timercmp(&now, &m_stoptime, >))
-
{
-
break;
-
}
-
}
-
// epoll 出错
-
if (nfds == -1)
-
{
-
std::cout << "epoll_wait error: " << strerror(errno) << std::endl;
-
continue;
-
}
-
// 处理被触发的事件
-
for (int i = 0; i < nfds; ++i)
-
{
-
int type = 0;
-
int fd = events[i].data.fd;
-
if (fd < 0) //fd出错
-
{
-
std::cout << "the FD is " << fd << std::endl;
-
continue;
-
}
-
FDEventHanderBase* pBase = m_handlerSet.GetFDEventHandler(fd, type);
-
if (NULL == pBase)
-
{
-
std::cout << "pBase is NULL, fd is" << fd << std::endl;
-
continue;
-
}
-
-
if (events[i].events & EPOLLIN)//read events
-
{
-
pBase->OnFDRead();
-
}
-
if (events[i].events & EPOLLOUT) //write events
-
{
-
pBase->OnFDWrite();
-
}
-
if (events[i].events & EPOLLERR) // error events
-
{
-
pBase->Close();
-
}
-
}
-
// 处理定时器事件
-
ScanTimer();
-
// 处理idle事件
-
} // end of while
-
-
std::cout << "stop epoll" << std::endl;
-
close(m_epfd); //close epoll fd
-
m_epfd = -1;
-
-
return true;
-
}
-
-
bool LTReactor::Stop() {
-
m_bRunning = false;
-
-
timeval val, now;
-
val.tv_usec = 50 * 1000; //50ms后停止
-
gettimeofday(&now, NULL);
-
timeradd(&val, &now, &m_stoptime);
-
return true;
-
}
-
// 注册读事件,
-
// @return: 0, success. else failed.
-
int LTReactor::RegisterReadEvent(FDEventHanderBase* pBase) {
-
int type = 0;
-
FDEventHanderBase* pHander = m_handlerSet.GetFDEventHandler(pBase->GetFD(),
-
type);
-
-
epoll_event event;
-
event.data.fd = pBase->GetFD();
-
event.events = type | EPOLLIN; // 注册读事件
-
-
int iRet = epoll_ctl(m_epfd, NULL == pHander ? EPOLL_CTL_ADD
-
: EPOLL_CTL_MOD, pBase->GetFD(), &event);
-
if (iRet == -1)
-
{
-
std::cout << "epoll_ctl error: " << strerror(errno) << std::endl;
-
return -1;
-
}
-
-
m_handlerSet.AddFDEventHandler(pBase, EPOLLIN);
-
return 0;
-
}
-
// 注册写事件
-
// @return: 0, success. else failed.
-
int LTReactor::RegisterWriteEvent(FDEventHanderBase* pBase) {
-
int type = 0;
-
FDEventHanderBase* pHandler = m_handlerSet.GetFDEventHandler(
-
pBase->GetFD(), type);
-
-
epoll_event event;
-
event.data.fd = pBase->GetFD();
-
event.events = type | EPOLLOUT; //注册写事件
-
-
int iRet = epoll_ctl(m_epfd, NULL == pHandler ? EPOLL_CTL_ADD
-
: EPOLL_CTL_MOD, pBase->GetFD(), &event);
-
if (iRet == -1)
-
{
-
std::cout << "epoll_ctl error: " << strerror(errno) << std::endl;
-
return -1;
-
}
-
-
m_handlerSet.AddFDEventHandler(pBase, EPOLLOUT);
-
return 0;
-
}
-
// 注销读事件
-
// @return: 0, success. else failed.
-
int LTReactor::UnRegisterReadEvent(FDEventHanderBase* pBase) {
-
int type = 0;
-
FDEventHanderBase* pHandler = m_handlerSet.GetFDEventHandler(
-
pBase->GetFD(), type);
-
epoll_event event;
-
event.data.fd = pBase->GetFD();
-
event.events = (type & ~EPOLLIN); // 取消读事件
-
-
int iRet = epoll_ctl(m_epfd, NULL == pHandler ? EPOLL_CTL_DEL
-
: EPOLL_CTL_MOD, pBase->GetFD(), &event);
-
if (iRet == -1)
-
{
-
std::cout << "epoll_ctl error: " << strerror(errno) << std::endl;
-
return -1;
-
}
-
-
m_handlerSet.DelFDEventHandler(pBase->GetFD(), EPOLLIN);
-
return 0;
-
}
-
-
// 注销写事件
-
// @return: 0, success. else failed.
-
int LTReactor::UnRegisterWriteEvent(FDEventHanderBase* pBase) {
-
int type = 0;
-
FDEventHanderBase* pHandler = m_handlerSet.GetFDEventHandler(
-
pBase->GetFD(), type);
-
epoll_event event;
-
event.data.fd = pBase->GetFD();
-
event.events = (type & ~EPOLLOUT); // 取消写事件
-
-
int iRet = epoll_ctl(m_epfd, NULL == pHandler ? EPOLL_CTL_DEL
-
: EPOLL_CTL_MOD, pBase->GetFD(), &event);
-
if (iRet == -1)
-
{
-
std::cout << "epoll_ctl error: " << strerror(errno) << std::endl;
-
return -1;
-
}
-
-
m_handlerSet.DelFDEventHandler(pBase->GetFD(), EPOLLOUT);
-
return 0;
-
}
-
// 注销读写事件
-
int LTReactor::UnRegisterAllEvent(FDEventHanderBase* pBase) {
-
epoll_event event;
-
event.data.fd = pBase->GetFD();
-
event.events = EPOLLOUT | EPOLLIN; // 取消读写事件
-
int iRet = epoll_ctl(m_epfd, EPOLL_CTL_DEL, pBase->GetFD(), &event);
-
if (iRet == -1)
-
{
-
std::cout << "epoll_ctl error: " << strerror(errno) << std::endl;
-
return -1;
-
}
-
-
m_handlerSet.DelFDEventHandler(pBase->GetFD(), EPOLLOUT | EPOLLIN);
-
return 0;
-
}
-
// 注册定时器
-
int LTReactor::RegisterTimer(TimerEventHanderBase* pBase) {
-
m_handlerSet.AddTimerEventHandler(pBase);
-
return 0;
-
}
-
// 注销定时器
-
int LTReactor::UnRegisterTimer(TimerEventHanderBase* pBase) {
-
m_handlerSet.DelTimerEventHandler(pBase);
-
return 0;
-
}
-
// 扫描,看是否有定时器的时间到了
-
void LTReactor::ScanTimer() {
-
m_handlerSet.ScanTimer();
-
}
-
-
/* **********************************
-
* 处理FD类的基类
-
* 当该fd被触发时,调用处理函数来进行处理
-
* ***********************************/
-
// 注册读事件
-
int FDEventHanderBase::RegisterReadEvent() {
-
return m_pReactor->RegisterReadEvent(this);
-
}
-
// 注册写事件
-
int FDEventHanderBase::RegisterWriteEvent() {
-
return m_pReactor->RegisterWriteEvent(this);
-
}
-
// 注销读事件
-
int FDEventHanderBase::UnRegisterReadEvent() {
-
return m_pReactor->UnRegisterReadEvent(this);
-
}
-
// 注销写事件
-
int FDEventHanderBase::UnRegisterWriteEvent() {
-
return m_pReactor->UnRegisterWriteEvent(this);
-
}
-
-
int FDEventHanderBase::GetFD() const {
-
return m_fd;
-
}
-
void FDEventHanderBase::SetFD(int fd) {
-
m_fd = fd;
-
}
-
// 设置非阻塞,返回0,success.
-
int FDEventHanderBase::SetNonBlock(int fd, bool bNonBlock/* = true*/) {
-
int flags = fcntl(fd, F_GETFL, 0);
-
if (flags == -1)
-
{
-
return -1;
-
}
-
if (bNonBlock)
-
flags |= O_NONBLOCK;
-
else
-
flags &= ~O_NONBLOCK;
-
-
if (fcntl(fd, F_SETFL, flags) == -1)
-
{
-
return -1;
-
}
-
-
return 0;
-
}
-
/* **********************************
-
* 处理timer类的基类
-
* 当timer被触发时,调用该类的函数
-
* **********************************/
-
// 注册定时器,@msec,多长时间响一次,单位:毫秒
-
// 由于epoll精度的限制,这个地方,精度只能达到 毫秒,但不是准确
-
int TimerEventHanderBase::RegisterTimer(unsigned int msec /*ms*/, bool restart)
-
{
-
m_bRestart = restart;
-
-
m_interval.tv_sec = msec / 1000;
-
m_interval.tv_usec = msec % 1000;
-
timeval now;
-
gettimeofday(&now, NULL);
-
timeradd(&now, &m_interval, &m_endtime);
-
return m_pReactor->RegisterTimer(this);
-
}
-
int TimerEventHanderBase::UnRegisterTimer() {
-
return m_pReactor->UnRegisterTimer(this);
-
}
-
int TimerEventHanderBase::RegisterTimerAgain() {
-
if (timerisset(&m_endtime) && timerisset(&m_interval))
-
{
-
timeval now;
-
gettimeofday(&now, NULL);
-
timeradd(&now, &m_interval, &m_endtime);
-
return m_pReactor->RegisterTimer(this);
-
}
-
return -1;
-
}
-
/* **********************************
-
* 处理类的集合
-
* 有个对应关系 -- fd -- 处理函数 -- read/write.
-
* *********************************/
-
// 增加fd事件, @type : EPOLLIN, EPOLLOUT,
-
void EventHanderSet::AddFDEventHandler(FDEventHanderBase* pHandler, int type) {
-
const int fd = pHandler->GetFD();
-
std::map<int, FDHandler>::iterator it = m_fdmap.find(fd);
-
if (it != m_fdmap.end())
-
{
-
it->second.type |= type;
-
it->second.pHandler = pHandler;
-
}
-
else
-
{
-
FDHandler th;
-
th.type = type;
-
th.pHandler = pHandler;
-
m_fdmap.insert(std::make_pair(fd, th));
-
}
-
}
-
// @type : EPOLLIN, EPOLLOUT
-
void EventHanderSet::DelFDEventHandler(int fd, int type) {
-
std::map<int, FDHandler>::iterator it = m_fdmap.find(fd);
-
if (it != m_fdmap.end())
-
{
-
it->second.type &= ~type;//去掉该属性
-
if (0 == it->second.type) //若所有的属性都去掉了,从map中删除该handler.
-
{
-
m_fdmap.erase(it);
-
}
-
}
-
}
-
// 根据fd,找到 FDEventHanderBase,及type.
-
FDEventHanderBase* EventHanderSet::GetFDEventHandler(int fd, int& type) {
-
std::map<int, FDHandler>::iterator it = m_fdmap.find(fd);
-
if (it != m_fdmap.end())
-
{
-
type = it->second.type;
-
return it->second.pHandler;
-
}
-
-
return NULL;
-
}
-
-
void EventHanderSet::AddTimerEventHandler(TimerEventHanderBase* pHandler) {
-
timeval endtime = pHandler->GetEndTime();
-
std::pair<long int, long int> t(endtime.tv_sec, endtime.tv_usec);
-
printf("addTimer: [%u:%u] \n", (unsigned int) t.first,
-
(unsigned int) t.second);
-
m_timerMinHeap.Insert(t);
-
m_timerMultiMap.insert(std::make_pair(t, pHandler));
-
}
-
void EventHanderSet::DelTimerEventHandler(TimerEventHanderBase* pHandler) {
-
timeval endtime = pHandler->GetEndTime();
-
std::pair<long int, long int> t(endtime.tv_sec, endtime.tv_usec);
-
std::multimap<std::pair<long int, long int>, TimerEventHanderBase*>::iterator
-
beg = m_timerMultiMap.lower_bound(t);
-
std::multimap<std::pair<long int, long int>, TimerEventHanderBase*>::iterator
-
end = m_timerMultiMap.upper_bound(t);
-
for (; beg != end; ++beg)
-
{
-
if (beg->second == pHandler)
-
{
-
m_timerMultiMap.erase(beg);
-
break;
-
}
-
}
-
}
-
void EventHanderSet::ScanTimer() {
-
-
while (true)
-
{
-
// printf("m_timerMinHeap: m_max_size[%d] m_cur_size[%d] \n",
-
// m_timerMinHeap.GetMaxSize(), m_timerMinHeap.GetCurSize());
-
if (!m_timerMinHeap.IsEmpty())
-
{
-
std::pair<long int, long int> minTime = m_timerMinHeap.GetMin(); //获取最小时间
-
timeval minTimeVal;
-
minTimeVal.tv_sec = minTime.first;
-
minTimeVal.tv_usec = minTime.second;
-
-
timeval now =
-
{ 0, 0 };
-
gettimeofday(&now, NULL);
-
if (timercmp(&now, &minTimeVal, >=)) //当前时间>=触发时间
-
{
-
m_timerMinHeap.RemoveMin(); //去掉最小堆里面的时间
-
std::multimap<std::pair<long int, long int>,
-
TimerEventHanderBase*>::iterator beg =
-
m_timerMultiMap.lower_bound(minTime);
-
-
for (; beg != m_timerMultiMap.upper_bound(minTime);)
-
{
-
TimerEventHanderBase* pHandler = beg->second;
-
pHandler->OnTimeOut();
-
if (pHandler->IsRestart()) //需要重启
-
{
-
AddTimerEventHandler(pHandler);
-
}
-
m_timerMultiMap.erase(beg++);//去掉multimap中的句柄
-
}
-
}
-
else
-
{
-
break;
-
}
-
}
-
else
-
{
-
break;
-
}
-
}
-
}
7. 测试代码
-
#include "reactor.h"
-
#include <stdio.h>
-
#include <string.h>
-
#include <unistd.h>
-
#include <sys/types.h>
-
#include <sys/stat.h>
-
#include <fcntl.h>
-
-
class TimerEventHandler_test: public TimerEventHanderBase
-
{
-
public:
-
TimerEventHandler_test(Reactor * pReactor) :
-
TimerEventHanderBase(pReactor)
-
{
-
-
}
-
void OnTimeOut() {
-
timeval t;
-
memset(&t, 0, sizeof(t));
-
gettimeofday(&t, NULL);
-
printf("timeOut: [%u:%u] \n", (unsigned int)t.tv_sec, (unsigned int)t.tv_usec);
-
}
-
};
-
-
void reactor_test_1() {
-
Reactor * pReactor = new LTReactor;
-
pReactor->Init();
-
TimerEventHanderBase* pHandler1 = new TimerEventHandler_test(pReactor);
-
pHandler1->RegisterTimer(2000, false);
-
TimerEventHanderBase* pHandler2 = new TimerEventHandler_test(pReactor);
-
pHandler2->RegisterTimer(4000, false);
-
TimerEventHanderBase* pHandler3 = new TimerEventHandler_test(pReactor);
-
pHandler3->RegisterTimer(8000, false);
-
TimerEventHanderBase* pHandler4 = new TimerEventHandler_test(pReactor);
-
pHandler4->RegisterTimer(10000, false);
-
pReactor->Run();
-
}
-
////////////////////////////////////////////////////////////////////////////
-
class FileFDEventHander: public FDEventHanderBase
-
{
-
public:
-
FileFDEventHander(int fd, Reactor* pReactor) :
-
FDEventHanderBase(fd, pReactor)
-
{
-
-
}
-
-
// 读被触发时,调用该函数
-
virtual void OnFDRead() {
-
char buf[1024] = {0};
-
read(m_fd, buf, sizeof(buf));
-
printf("FDReadResult: [%s] \n", buf);
-
UnRegisterReadEvent();
-
}
-
// 写被触发时,调用该函数
-
virtual void OnFDWrite() {
-
char buf[] = "this is a test file !";
-
write(m_fd, buf, strlen(buf));
-
-
UnRegisterWriteEvent();
-
}
-
// 关闭fd
-
virtual void Close() {
-
close(m_fd);
-
}
-
};
-
-
void reactor_test_2()
-
{
-
int fd = -1;
-
const char* path = "/home/ll/work/min_heap/test.txt";
-
if(0 != mkfifo(path, 0777)) // 创建一个pipe.
-
{
-
fd = open(path, O_RDWR);
-
}
-
-
Reactor * pReactor = new LTReactor;
-
pReactor->Init();
-
-
FDEventHanderBase* pHandler = new FileFDEventHander(fd, pReactor);
-
// 注册写事件,在命令行 cat pipe_file_name
-
// pHandler->RegisterWriteEvent();
-
// sleep(5);
-
// printf("sleep 5s over \n");
-
// 注册读事件,在命令行 echo "dfsdf" > pipe_file_name
-
pHandler->RegisterReadEvent();
-
sleep(5);
-
printf("sleep 5s over \n");
-
pReactor->Run();
-
}
8. 需要注意的信号
SIGPIPE:Broken pipe: write to pipe with no readers,对socket的两端A和B,若B已经关闭。当A第一次写时,内核会返回RST
给应用程序;当A第二次写,内核会返回SIGPIPE信号给应用程序。所以A端需要处理SIGPIPE信号。SIGPIPE默认动作是进程退出,可以忽略该信号,
signal(SIGPIPE, SIG_IGN)。
SIGINT:当用户按ctl+c时,会产生SIGINT信号。可以用来终止进程。signal(SIGINT, proc_exit);
SIGKILL / SIGSTOP:不能被捕捉或忽略的信号。提供了一种可以杀死进程的方法。signal(SIGKILL/SIGSTOP, proc_exit);
SIGTERM:Termination signal,由kill命名发出的系统默认终止信号。signal(SIGTERM, proc_exit);
阅读(3587) | 评论(0) | 转发(0) |