libevent库怎么写一个定时器事件Timer

胖瑶大大_4621

胖瑶大大_4621

2026-09-30

585人浏览

原创

用event_new创建一次性定时器需设fd为-1、传ev_timeout、设timeval超时值并调用event_add()启动;重复定时器须在回调末尾重新调用event_add();取消用event_del(),不可重用已del的event对象。

libevent库怎么写一个定时器事件timer

怎么用 event_new 创建一个一次性定时器

libevent 的定时器本质是带超时的事件,不是独立类型;必须用 event_new 绑定一个回调函数,并设置超时时间。关键点在于:不能只传 EV_TIMEOUT,还得把 fd 设为 -1(表示无文件描述符),否则 event 可能被误判为 I/O 事件而无法触发。

常见错误是传了合法 fd(比如 0)还加 EV_TIMEOUT,结果定时器根本不回调——因为 libevent 认为这是个“监听 stdin 可读 + 超时”的混合事件,而 stdin 并不满足可读条件,超时逻辑就被压制了。

  • 回调函数签名必须是 void (*cb)(evutil_socket_t, short, void *),第三个参数是用户数据
  • 超时时间用 struct timeval,注意 tv_sec 和 tv_usec 都为 0 表示“立即触发”,但某些老版本 libevent 在 tv_sec == 0 && tv_usec == 0 时行为不稳定,建议至少设 tv_usec = 1
  • 调用 event_add() 才真正启动定时器;漏掉这步,事件永远不生效

怎么实现重复执行的定时器(如每秒一次)

libevent 没有原生的 “repeat” 标志,重复定时器靠在回调里重新调用 event_add() 实现。这不是 bug,是设计选择:避免隐式状态,把控制权完全交给用户。

容易踩的坑是忘记在回调中再次调用 event_add(),或者错误地在回调外反复调用 event_add()(导致多个 pending 事件堆积)。正确做法是在回调末尾重设超时并再加一次:

void on_timer(evutil_socket_t fd, short what, void *arg) {
    printf("tick\n");
    struct event *ev = (struct event *)arg;
    struct timeval one_sec = {1, 0};
    event_add(ev, &one_sec); // 重新加入事件循环
}

注意:不要在回调里调用 event_free(),否则下一次 event_add() 会 crash;释放必须在确定不再需要时,由外部逻辑统一处理。

Consensus
Consensus

一款AI工具,主要用于一个新型搜索引擎,利用AI在科学研究中为你找到答案,适合需要提升相关任务效率的用户。

下载

event_pending() 和 event_del() 怎么安全取消定时器

想中途停掉一个还没触发的定时器?必须用 event_del()。它会从 event_base 中移除该事件,之后即使超时也不会回调。如果只是想确认是否还在 pending 状态,用 event_pending() 检查返回值是否含 EV_TIMEOUT。

典型误操作:调用 event_del() 后又对同一 struct event * 调用 event_add() —— 这是未定义行为,多数情况下会 segfault。libevent 不允许重用已被 event_del() 的 event 对象,必须重新 event_new()。

  • event_del() 是线程不安全的,若 timer 在其他线程中运行,需确保调用前已同步停止 event loop 或使用 event_base_loopbreak() 配合主循环检查
  • 如果 timer 回调正在执行,event_del() 仍可安全调用,它只影响 future 触发,不影响当前正在跑的回调

为什么 event_base_dispatch() 不返回,以及怎么优雅退出

定时器要工作,必须让 event loop 跑起来。event_base_dispatch() 是阻塞的,直到所有事件都已删除且无 pending 事件才返回。如果你只加了一个定时器又没设循环重装,它触发一次就退出,程序直接结束。

真正实用的写法是配合 event_base_loop() 并传入 EVLOOP_NO_EXIT_ON_EMPTY,这样即使暂时没事件,loop 也不会退出,方便后续动态增删 timer。退出时推荐先 event_del() 所有 timer,再调用 event_base_loopbreak(),最后 event_base_free()。

别依赖信号或全局 flag 强行 break loop——libevent 的事件调度依赖内部状态一致性,粗暴中断可能让 pending timer 残留或内存泄漏。

相关文章

PHP速学视频免费教程(入门到精通)
PHP速学视频免费教程(入门到精通)

PHP怎么学习?PHP怎么入门?PHP在哪学?PHP怎么学才快?不用担心,这里为大家提供了PHP速学教程(入门到精通),有需要的小伙伴保存下载就能学习啦!

下载

相关标签:

本站声明:本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系admin@php.cn

相关专题

更多
PDF转图片方法
PDF转图片方法

需要把 PDF 页面用于上传、预览、分享或图片归档时,PDF 转图片方法专题整理 JPG/PNG 格式选择、逐页导出、清晰度设置、批量下载和结果检查等流程,帮助用户稳定完成 PDF 图片化处理。

2026.09.30

0

26

PixTV AI视频生成与无限画布创作
PixTV AI视频生成与无限画布创作

PixTV专题整理AI视频与视觉内容创作相关功能使用教程,涵盖AI生图、视频生成、无限画布、多模型创作、素材管理、声音音乐及视频剪辑等功能,帮助用户快速掌握PixTV从创意到成片的完整制作方法。

2026.09.29

0

15

Buffalo框架数据库开发全教程
Buffalo框架数据库开发全教程

本专题围绕Buffalo框架数据库开发,讲解database.yml多环境配置、soda与fizz迁移生成回滚、模型结构体标签、增删改查与条件查询、一对多与多对多关联、数据校验、回调钩子、事务处理及原生SQL执行能力。

2026.09.23

200

15

Buffalo框架路由与请求处理实操指南
Buffalo框架路由与请求处理实操指南

本专题讲解Buffalo框架路由与请求处理机制,涵盖路由注册与分组、资源路由、Handler编写规范、Context上下文方法、参数绑定、中间件编写挂载、Session与Cookie读写、Flash消息及错误页面定制方法。

2026.09.23

120

15

Buffalo框架零基础入门教程
Buffalo框架零基础入门教程

本专题整理Buffalo框架入门内容,涵盖Go环境准备、buffalo CLI安装、新项目生成、目录结构说明、dev热加载启动、数据库连接配置与常见报错排查,帮助新手按约定优于配置的思路跑通第一个Buffalo框架应用。

2026.09.23

100

15

Conan创建软件包配方指南
Conan创建软件包配方指南

本专题介绍通过conanfile.py创建软件包的方法,讲解包名、版本、依赖和构建设置等基础信息,以及source、build、package、package_info等常用方法的作用及编写思路。

2026.09.22

60

12

Conan二进制包配置指南
Conan二进制包配置指南

本专题介绍Conan根据操作系统、编译器、架构和构建类型生成二进制包的方法,讲解Profile、Settings、Options及Package ID的作用,帮助管理不同平台和编译环境下的包版本。

2026.09.22

80

13

Conan私有仓库搭建教程
Conan私有仓库搭建教程

本专题系统的讲解Conan私有仓库的搭建流程,涵盖仓库服务部署、存储目录配置、用户认证、权限划分和远程地址添加,并介绍内部C++依赖包的上传、下载及版本维护方法。

2026.09.22

60

19

loomy官网入口地址合集
loomy官网入口地址合集

本专题汇总了 Loomy 桌面 AI 助理的官方入口地址合集及使用指南。提供 macOS 与 Windows 客户端下载 。Loomy 是讯飞推出的桌面级 AI 工作搭子,支持文件整理、数据分析、网页操作及通过飞书/钉钉远程操控电脑,助你高效完成本地办公任务 。

2026.09.22

80

19

热门下载

更多
网站特效
/
网站源码
/
网站素材
/
前端模板

精品课程

更多
热门推荐
/
最新课程
phpStudy极速入门视频教程
phpStudy极速入门视频教程

共6课时 | 54.6万人学习

独孤九贱(4)_PHP视频教程
独孤九贱(4)_PHP视频教程

共89课时 | 133.4万人学习