#ifndef __MYTIMER_H_
#define __MYTIMER_H_ /***************
高并发场景下的定时器
*****************/ //定时器回调函数
typedef void *(*TimerCallback)(int fd, void *); typedef enum enFD_TYPE
{
FD_TIMER,
FD_SOCKET,
FD_FILE,
}ENFD_TYPE; struct STEpollParam
{
int fd; //文件描述符
ENFD_TYPE enType; //文件描述符类型
TimerCallback cb; //定时器回调函数
void * pvParam; //回调函数参数
}; //创建定时器对象
int createTimer(unsigned int uiSec, unsigned int uiNsec); //设置文件描述符非阻塞
int setNoBlock(int fd); //创建epoll
int createEpoll(); //添加文件描述符到epoll
int addFdToEpoll(int epfd, STEpollParam *pstParam); //消息处理
int recvMsg(void *pvParam); //等待消息
void epollWait(int epfd); #endif
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <fcntl.h>
#include <sys/epoll.h>
#include <sys/timerfd.h>
#include <string.h> #include "comontype.h"
#include "mytimer.h" #define EPOOL_SIZE 32000
#define EPOOL_EVENT 32 /********************************************************
Func Name: createTimer
Date Created: 2018-7-30
Description: 创建定时器对象
Input: uiTvSec:设置间隔多少秒
uiTvUsec:设置间隔多少微秒
Output:
Return: 文件句柄
Caution:
*********************************************************/
int createTimer(unsigned int uiSec, unsigned int uiNsec)
{
int iRet = ;
int tfd = ;
struct itimerspec timeValue; //初始化定时器
/*
When the file descriptor is no longer required it should be closed.
When all file descriptors associated with the same timer object have been closed,
the timer is disarmed and its resources are freed by the kernel. 意思是该文件句柄还是需要调用close函数关闭的
*/
tfd = timerfd_create(CLOCK_REALTIME,);
if (tfd < )
{
return -;
} //设置开启定时器
/*
Setting either field of new_value.it_value to a nonzero value arms the timer.
Setting both fields of new_value.it_value to zero disarms the timer.
意思是如果不设置it_interval的值非零,那么即关闭定时器
*/
timeValue.it_value.tv_sec = ;
timeValue.it_value.tv_nsec = ; //设置定时器周期
timeValue.it_interval.tv_sec = (time_t)uiSec;
timeValue.it_interval.tv_nsec = (long)uiNsec; iRet = timerfd_settime(tfd, , &timeValue, NULL);
if (iRet < )
{
return -;
} return tfd;
} /********************************************************
Func Name: setNoBlock
Date Created: 2018-7-27
Description: 设置文件描述符非阻塞
Input: fd:文件描述符
Output:
Return: error code
Caution:
*********************************************************/
int setNoBlock(IN int fd)
{
int iRet = DEFAULT_ERROR; int iOption = -; iOption = fcntl(fd, F_GETFD);
if(iOption < )
{
iRet = DEFAULT_ERROR;
return iRet;
} iOption = iOption | O_NONBLOCK; iOption = fcntl(fd,F_SETFD,iOption);
if(iOption < )
{
iRet = DEFAULT_ERROR;
return iRet;
} return RESULT_OK;
} /********************************************************
Func Name: createEpoll
Date Created: 2018-7-30
Description: 创建epoll
Input:
Output:
Return: epoll句柄
Caution:
*********************************************************/
int createEpoll()
{
int epfd = ; /*
When no longer required,
the file descriptor returned by epoll_create() should be closed byusing close(2).
When all file descriptors referring to an epoll instance have been closed,
the kernel destroys the instance and releases the associated resources for reuse. 意思是用完需要调用close函数关闭epoll句柄
*/
epfd = epoll_create(EPOOL_SIZE);
if (epfd < )
{
return -;
} return epfd;
} /********************************************************
Func Name: addFdToEpoll
Date Created: 2018-7-30
Description: 添加文件描述符到epoll
Input:
Output:
Return: error code
Caution:
*********************************************************/
int addFdToEpoll(int epfd, STEpollParam *pstParam)
{
int iRet = DEFAULT_ERROR;
struct epoll_event ev;
ev.data.ptr = pstParam;
ev.events = EPOLLIN | EPOLLERR | EPOLLHUP;
iRet = epoll_ctl(epfd, EPOLL_CTL_ADD, pstParam->fd, &ev);
if (iRet < )
{
return DEFAULT_ERROR;
}
return RESULT_OK;
} /********************************************************
Func Name: recvMsg
Date Created: 2018-7-30
Description: 消息处理
Input: pvParam:参数指针
Output:
Return:
Caution:
*********************************************************/
int recvMsg(void *pvParam)
{
int iRet = DEFAULT_ERROR;
STEpollParam * pstParam = NULL; if (NULL == pvParam)
{
iRet = PARAM_ERROR;
return iRet;
}
pstParam = (STEpollParam *)pvParam;
switch(pstParam->enType)
{
case FD_TIMER:
pstParam->cb(pstParam->fd, pstParam->pvParam);
break;
default:
break;
}
return RESULT_OK;
} /********************************************************
Func Name: epollWait
Date Created: 2018-7-30
Description: 等待消息
Input: epfd:epoll句柄
Output:
Return:
Caution:
*********************************************************/
void epollWait(int epfd)
{
int i = ;
int nfds = ;
struct epoll_event *events = NULL; //分配epoll事件内存
events = (struct epoll_event *)malloc(sizeof(struct epoll_event)*EPOOL_EVENT);
if (NULL == events)
{
return ;
}
memset(events, , sizeof(struct epoll_event)*EPOOL_EVENT); for (;;)
{
nfds = epoll_wait(epfd, events, EPOOL_EVENT, -);
if (nfds < )
{
break;
}
for (i = ; i < nfds; i++ )
{
//监听读事件
if (events[i].events & EPOLLIN)
{
recvMsg(events[i].data.ptr);
}
}
} //关闭epoll
close(epfd); return ;
}
#include <iostream>

using namespace std;

#include "mytimer.h"

//#include <sys/timerfd.h>
#include <string.h>
#include <stdlib.h>
#include <stdio.h>
#include <unistd.h>
#include "comontype.h" #define INTERVAL 3 void * timerFunc(int fd, void *pvParam)
{
long data = ;
int *p = NULL; p = (int *)pvParam;
read(fd, &data, sizeof(long));
printf("data = %lu and p = %d \n", data, *p); return NULL;
} int test()
{
STEpollParam *pstParam =new STEpollParam;
int tfd = ;
int num = ; //初始化epoll
int epfd = createEpoll();
if (epfd < )
{
cout << "createEpoll() failed ." << endl;
return -;
}
//初始化定时器
tfd = createTimer(INTERVAL,);
if (tfd < )
{
cout << "createTimer() failed ." << endl;
return -;
} pstParam->fd = tfd;
pstParam->enType = FD_TIMER;
pstParam->cb = timerFunc;
pstParam->pvParam = &num; addFdToEpoll(epfd, pstParam); epollWait(epfd); //关闭定时器文件描述符
close(tfd); DE_FREE(pstParam); return ;
} int main()
{
test();
getchar();
return ;
}

Linux epoll版定时器的更多相关文章

  1. Java NIO系列教程(七) selector原理 Epoll版的Selector

    目录: Reactor(反应堆)和Proactor(前摄器) <I/O模型之三:两种高性能 I/O 设计模式 Reactor 和 Proactor> <[转]第8章 前摄器(Proa ...

  2. 源码剖析Linux epoll实现机制及Linux上惊群

    转载:https://blog.csdn.net/tgxallen/article/details/78086360 看源码是对一个技术认识最直接且最有效的方式了,之前用Linux Epoll做过一个 ...

  3. 如何在Python中使用Linux epoll

    如何在Python中使用Linux epoll 内容 介绍 阻塞套接字编程示例 异步套接字和Linux epoll的好处 epoll的异步套接字编程示例 性能考量 源代码 介绍 从2.6版开始,Pyt ...

  4. 在同一个硬盘上安装多个 Linux 发行版及 Fedora 21 、Fedora 22 初体验

    在同一个硬盘上安装多个 Linux 发行版 以前对多个 Linux 发行版的折腾主要是在虚拟机上完成.我的桌面电脑性能比较强大,玩玩虚拟机没啥问题,但是笔记本电脑就不行了.要在我的笔记本电脑上折腾多个 ...

  5. 2016 最佳 Linux 发行版排行榜

    2015年,不管在企业市场还是个人消费市场都是 Linux非常重要的一年.作为一个自2005年起就开始使用 Linux的 Linuxer ,我门见证了 Linux在过去十年的成长.2016 Linux ...

  6. 构建自己的 Linux 发行版

    如何用 SUSE Studio 构建 Linux 发行版? (1) 进入到 www.susestudio.com,设立一个帐户 (2) 为你的设备(发行版)选择一个基本模板 -软件和软件包选择 (1) ...

  7. linux发行版基础目录

    linux发行版基础目录 linux 基础目录 linux基础目录 目录 作用 / 根目录,起源 /boot linux引导启动目录 /lib 库目录 /bin 常用内部命令 /sbin 常用内部管理 ...

  8. 2016年最佳Linux发行版排行榜

    2015年,不管在企业市场还是个人消费市场都是 Linux 非常重要的一年. 最好的回归发行版:openSUSE openSUSE 背后的 SUSE 公司是最老的 Linux 企业,它成立于 Linu ...

  9. 最适合和最不适合新手使用的几款 Linux 发行版

    大多数知名的Linux发行版都属于"比较容易使用"这一类.一些观察人士可能会驳斥这个观点,但事实上,说到Linux,大多数并非从事IT或软件开发工作的人会被最容易的使用体验所吸引. ...

随机推荐

  1. jmeter http协议---cookie处理

    使用jmeter测试的http接口的时候,经常遇到需要cookie做免登录等作用的情况,jmeter如何在测试http接口的时候加载所需cookie呢?主要分两步 一. 收集对应站点的cookie 1 ...

  2. octave画心形曲线

    octave是gnu出品和matlab兼容的科学计算软件,具有体积小,兼容性好,免费的优点. 心形曲线是根据函数:( x2 + y2 -1 )3 - x2y3=0 改编而成. clear all; c ...

  3. 批处理向FTP上传指定属性的文件 批处理增量备份的例子

    使用windows批处理向FTP上传具有指定属性的文件,类似增量备份功能. 对一个目录里的几个文件自动上传FTP时只上传有归档属性的文件,然后FTP上传成功后自动清除(本机)刚上传文件的归档属性. 类 ...

  4. 译: 2. Apache Axis2安装指南

    Apache Axis2安装指南 本文档提供有关Axis2分发包,系统先决条件以及设置环境变量和工具的信息,然后提供有关安装方法的详细说明. 请将您的反馈发送至:java-dev@axis.apach ...

  5. vue2.x 路由懒加载 优化打包体积

    当打包构建应用时,Javascript 包会变得非常大,影响页面加载.如果我们能把不同路由对应的组件分割成不同的代码块,然后当路由被访问的时候才加载对应组件,这样就更加高效了. 结合 Vue 的异步组 ...

  6. nfs 客户端启动报错rpc.mountd: svc_tli_create: could not open connection for tcp6

    # /etc/init.d/nfs start Starting NFS services: [ OK ] Starting NFS mountd: rpc.mountd: svc_tli_creat ...

  7. matlab问题集总

    每次更新一点,慢慢增加 nargin nargin是用来判断输入变量个数的函数,这样就可以针对不同的情况执行不同的功能.通常可以用他来设定一些默认值,如下面的函数. 例子,函数test1的功能是输出a ...

  8. linux命令(44):sed,vim;去掉文件中的^M 符号,去掉行首空格和制表符

    注:下面的直接粘贴会出错,要重新输入^M 如何输入^M,先 ctrl+v,然后 ctrl+m 第一种方法: cat -A filename 就可以看到windows下的断元字符 ^M要去除他,最简单用 ...

  9. MySQL索引的维护与优化——查找重复及冗余索引

    方法一:通过MySQL的information_schema数据库 查找重复与冗余索引 SELECT a.table_schema AS '数据库', a.table_name AS '表名', a. ...

  10. oracle Plsql 执行update或者delete时卡死问题解决办法

    PLSQL删除记录 delete from OT_Table 程序一直在执行... 原因: 在执行  修改 的时候没有commit,oracle将该记录锁住了. 可以通过以下办法解决: 先查询锁定记录 ...