IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> 数据结构与算法 -> 【openwrt】libubox组件——uloop_timeout -> 正文阅读

[数据结构与算法]【openwrt】libubox组件——uloop_timeout

Libubox 是 OpenWrt 的一个必备的基础库,包含大小端转换、链表、MD5 、定时器等实用工具基础库。
Libubox提供的定时器工具用来实现一些简单的定时任务十分方便。
下面介绍其定时器工具的使用方法:

定时器工具主要数据结构和函数

struct uloop_timeout
{
	struct list_head list;
	bool pending;

	uloop_timeout_handler cb;
	struct timeval time;
};

struct uloop_timeout用来描述一个定时器,cb是该定时器的超时回调函数,time是定时器超时时间,它是一个未来的时间。

//添加一个定时器,定时时间需要我们自己预先设定
int uloop_timeout_add(struct uloop_timeout *timeout);

//添加一个定时器,并设置超时时间,单位ms
int uloop_timeout_set(struct uloop_timeout *timeout, int msecs);

//删除一个定时器
int uloop_timeout_cancel(struct uloop_timeout *timeout);

//计算一个定时器还有多久超时,单位ms
int uloop_timeout_remaining(struct uloop_timeout *timeout);
Libubox 提供的定时器都是一次性定时器,如果需要循环触发,需要重复设置定时器。

定时器工具原理

uloop.c中有维护一条定时器链表timeouts

static struct list_head timeouts = LIST_HEAD_INIT(timeouts);

uloop_timeout_setuloop_timeout_add会将新的定时器添加到链表,并且新的定时器按照超时时间由近到远的顺序被添加进链表

在这里插入图片描述

  • timer1 3s后超时
  • timer2 6s后超时
  • timer3 10后超时

它的实现方式如下:

int uloop_timeout_add(struct uloop_timeout *timeout)
{
	struct uloop_timeout *tmp;
	struct list_head *h = &timeouts;

	if (timeout->pending)
		return -1;
	
	//遍历timeouts链表,找到超时时间比新增的定时器长的成员
	list_for_each_entry(tmp, &timeouts, list) {
		if (tv_diff(&tmp->time, &timeout->time) > 0) {
			h = &tmp->list;
			break;
		}
	}
	
	//将新增定时器插入到该成员的前面
	list_add_tail(&timeout->list, h);
	timeout->pending = true;
	return 0;
}

uloop_run中会遍历定时器链表,对于已经超时的定时器会执行其回调函数。

static void uloop_process_timeouts(struct timeval *tv)
{
	struct uloop_timeout *t;

	while (!list_empty(&timeouts)) {
		
		//取出定时器链表中第一个成员进行判断,因为这些成员是按照超时时间由近到远的顺序,所以第一个成员肯定是最先超时
		t = list_first_entry(&timeouts, struct uloop_timeout, list);

		if (tv_diff(&t->time, tv) > 0)
			break;//未超时 直接退出

		uloop_timeout_cancel(t);
		if (t->cb)
			t->cb(t);
	}
}

uloop_process_timeouts()每次只处理timeouts中第一个成员(不是一次性处理完链表中所有的定时器),但是这个函数本身会被循环调用。

定时器工具实例

如下实例定义一个超时时间为2s的定时器u_tim ,并在回调函数中重新设置超时时间,使其循环触发。
循环3次后,取消这个定时器。

#include "stdio.h"
#include "uloop.h" //uloop_timeout_xxx
#include <sys/time.h> // struct timeval

static void u_tim_cb(struct uloop_timeout *timeout)
{
    static int cnt = 0;
	printf("Enter timer cb! second %ld cnt=%d\n",timeout->time.tv_sec,cnt);
	uloop_timeout_set(timeout, 2000);
    cnt++;

    if( cnt == 3 )
    {
        uloop_timeout_cancel(timeout);
        printf("timer cancel!\n");
    }

}

static struct uloop_timeout u_tim = {
	.cb = u_tim_cb,
};

int main()
{
    uloop_init();
    uloop_timeout_set(&u_tim, 2000);
    
    printf("Enter uloop run!\n");    
    uloop_run();
    return 0;
}

  数据结构与算法 最新文章
【力扣106】 从中序与后续遍历序列构造二叉
leetcode 322 零钱兑换
哈希的应用:海量数据处理
动态规划|最短Hamilton路径
华为机试_HJ41 称砝码【中等】【menset】【
【C与数据结构】——寒假提高每日练习Day1
基础算法——堆排序
2023王道数据结构线性表--单链表课后习题部
LeetCode 之 反转链表的一部分
【题解】lintcode必刷50题<有效的括号序列
上一篇文章      下一篇文章      查看所有文章
加:2022-05-04 07:30:14  更:2022-05-04 07:30:35 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/26 5:20:47-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码