• Linux 内核定时器(高级字符设备五)


    一、Linux 内核定时器介绍

      在 Linux 内核中很多函数是基于定时器进行驱动的,但是内核定时器的精度并不高,所以不能作为高精度定时器使用。并且内核定时器的运行没有周期性,到达计时终点后会自动关闭。如果要实现周期性定时,就要在定时处理函数中重新开启定时器。
      Linux 内核中使用 timer_list 结构体表示内核定时器,该结构体定义在“内核源码/include/linux/timer.h”文件中,具体内容如下所示:

    struct timer_list {
    	/*
    	 * All fields that change during normal runtime grouped to the
    	 * same cacheline
    	 */
    	struct hlist_node	entry;
    	unsigned long		expires;
    	void			(*function)(struct timer_list *);
    	u32			flags;
    
    #ifdef CONFIG_LOCKDEP
    	struct lockdep_map	lockdep_map;
    #endif
    
    	ANDROID_KABI_RESERVE(1);
    	ANDROID_KABI_RESERVE(2);
    };
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17

      使用以下宏对 timer_list 结构体进行定义,_name 为定义的结构体名称,_function为定时处理函数,该宏同样定义在文件 “内核源码/include/linux/timer.h”文件中,如下所示:

    #define DEFINE_TIMER(_name, _function)				\
    	struct timer_list _name =				\
    		__TIMER_INITIALIZER(_function, 0)
    
    • 1
    • 2
    • 3

      例如可以使用以下代码对定时器和相应的定时处理函数进行定义

    DEFINE_TIMER(timer_test,function_test);//定义一个定时器
    
    • 1

      定时器定义完成之后还需要通过一系列的 API 函数来初始化此定时器,部分函数说明如下

    函数作用
    void add_timer(struct timer_list *timer)向 Linux 内核注册定时器,使用add_timer 函数向内核注册定时器以后,定时器就会开始运行
    int del_timer(struct timer_list * timer)删除一个定时器
    int mod_timer(struct timer_list *timer,unsigned long expires)修改定时值,如果定时器还没

      在使用 add_timer()函数向 Linux 内核注册定时器之前,还需要设置定时时间,定时时间由 timer_list 结构体中的 expires 参数所确定,单位为节拍数。

    二、代码示例

    2.1、程序示例

    #include 
    #include 
    #include 
    
    static void function_test(struct timer_list *t);//定义function_test定时功能函数
    DEFINE_TIMER(timer_test,function_test);//定义一个定时器
    static void function_test(struct timer_list *t)
    {
    	printk("this is function test \n");
    	mod_timer(&timer_test,jiffies_64 + msecs_to_jiffies(5000));//使用mod_timer函数将定时时间设置为五秒后
    }	
    static int __init timer_mod_init(void) //驱动入口函数
    {
    	timer_test.expires = jiffies_64 + msecs_to_jiffies(5000);//将定时时间设置为五秒后
    	add_timer(&timer_test);//添加一个定时器
    	return 0;
    }
    
    static void __exit timer_mod_exit(void) //驱动出口函数
    {
    	del_timer(&timer_test);//删除一个定时器
    	printk("module exit \n");
    }
    module_init(timer_mod_init);
    module_exit(timer_mod_exit);
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25

    2.2、Linux 内核定时器使用API要点

    DEFINE_TIMER(timer_test,function_test);//定义一个定时器
    
    • 1
    add_timer(&timer_test);//添加一个定时器
    
    • 1
    static void function_test(struct timer_list *t)
    {
    	printk("this is function test \n");
    	mod_timer(&timer_test,jiffies_64 + msecs_to_jiffies(5000));//使用mod_timer函数将定时时间设置为五秒后
    }	
    
    • 1
    • 2
    • 3
    • 4
    • 5
  • 相关阅读:
    Java 同步锁ReentrantLock与抽象同步队列AQS
    MySql常见复合查询(重点)
    MFC入门基础(十一)控件编程示例
    fseek()函数 和 ftell()函数
    Win10 屏蔽键盘按键
    微服务之分布式事务服务端搭建(seata 1.0以下版本)
    CUDA 环境搭建
    顺丰快递商家寄件发货接口API类型和接入流程方案【快递100接口Demo】
    数据分析综述
    CentOS7虚拟机部署Part1
  • 原文地址:https://blog.csdn.net/xxxx123041/article/details/134042498