linux内核定时器编程

一.linux内核定时器基本结构和函数

1)struct timer_list 一个struct timer_list对应了一个定时器。
#include <linux/timer.h>
以下列出常用的接口:
struct timer_list
  {
   struct list_head entry;//定时器列表
   unsigned long expires;//定时器服务函数开始执行时间
   void (*function)(unsigned long);//定时器处理函数
   unsigned long data;//定时时间到时,data参数会传入服务函数
   struct timer_base *base;
  }
 定时器期满后,function()成员被执行,data参数传入服务函数,expires是定时器到期的时间(jiffies).
-----------使用定时器的步骤--------------
1.定义一个定时器
struct timer_list my_timer;
2.初始化定时器
void init_timer(struct timer_list* timer)//初始化一个定时器
此函数初始化timer_list的entry的next为NULL,并给base指针赋值。
TIMER_INITIALIZER(_function,_expires,_data)宏用于赋值定时器结构体的function,expires,data和base成员。
这个宏的定义如下:
#define TIMER_INITIALIZER(_function,_expires,_data)
{
	.function=(_function),
	.expires=(_expires),
	.data=(_data),
	.base=&__init_timer_base,
}
DEFINE_TIMER(_name,_function,_expires,_data)宏是定义并初始化定时器成员的"快捷方式"。
这个宏定义如下所示:
#define DEFINE_TIMER(_name,_function,_expires,_data) \
	struct timer_list  _name=    \
		TIMER_INITIALIZER(_function,_expires,_data)
3.增加定时器
void add_timer(struct timer_list *timer);
上述函数用于注册内核定时器,将定时器加入到内核动态定时器链表中。
4.删除定时器
int del_timer(struct timer_list *timer);
上述函数用于删除定时器。
del_timer_sync()是del_timer()的同步版,主要在多处理器系统中使用,如果编译内核不支持SMP,两者等价。
5.修改定时器的expire
int mod_timer(struct timer_list *timer ,unsigned long expires);
用于修改定时器的到期时间,在新的被传入的expires到来之后才会执行定时器的函数。
-------------------------------------------------
eg:内核定时器使用模板
//xxx设备结构体
struct xxx_dev
{
	struct cdev cdev;
	...
	timer_list xxx_timer;//设备要使用的定时器
}
//xxx驱动中的某函数
xxx_funcl(...)
{
	struct xxx_dev *dev=filp->private_data;
	...
	//初始化定时器
	init_timer(&dev->xxx_timer);
	dev->xxx_timer.function=&xxx_do_timer;
	dev->xxx_timer.data=(unsigned long)dev;//设备结构体指针作为定时器处理函数参数
	dev->xxx_timer.expires=jiffies+delay;
	//添加定时器
	add_timer(&dev->xxx_timer);
	...
}
//xxx驱动的某函数
xxx_fun2(...)
{
	...
	//删除定时器
	del_timer(&dev->xxx_timer);
	...
}
//定时器处理函数
static void xxx_do_timer(unsigned long arg)
{
	struct xxx_device *dev=(struct xxx_device *)(arg);
	...
	//调度定时器再执行
	dev->xxx_timer.expires=jiffies+delay;
	add_timer(&dev->xxx_timer);
	...
}
在定时器处理函数中,在做完相应的工作后,往往会延后expires并将定时器再次添加到内核定时器链表中,以便定时器能再次被触发。
二.以下是一个定时1s的驱动程序,直接上代码
timer_dev.c
#include <linux/miscdevice.h>
#include <linux/delay.h>
#include <asm/irq.h>
//#include <mach/regs-gpio.h>
//#include <mach/hardware.h>
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/init.h>
#include <linux/mm.h>
#include <linux/fs.h>
#include <linux/types.h>
#include <linux/delay.h>
#include <linux/moduleparam.h>
#include <linux/slab.h>
#include <linux/errno.h>
#include <linux/ioctl.h>
#include <linux/cdev.h>
#include <linux/string.h>
#include <linux/list.h>
#include <linux/pci.h>
#include <asm/uaccess.h>
#include <asm/atomic.h>
#include <asm/unistd.h>
#include <asm/io.h>
#include <asm/system.h>
#include <asm/uaccess.h>
#define TIMER_MAJOR 120
#define TIMER_MINOR 0
dev_t timer_dev_t;//设备号
dev_t timer_dev_major=TIMER_MAJOR;
dev_t timer_dev_minor=TIMER_MINOR;
struct TIMER_DEV
{
  struct cdev cdev;
  atomic_t count;
  struct timer_list timer_list;

};
struct TIMER_DEV* timer_dev;
//---------timer interrupt function----------------
static void timer_function(unsigned long data)
{
mod_timer(&(timer_dev->timer_list),jiffies+HZ);//重新设置时间
printk("current jiffies is %ld,count=%d\n",jiffies,timer_dev->count);
//(timer_dev->count)++;
atomic_inc(&(timer_dev->count));
}
//--------timer release function--------------------
static int timer_release(struct inode* inode, struct file* filp)
{
del_timer_sync(&(timer_dev->timer_list));
return 0;
}

//----------------file open function-----------------
static int timer_open(struct inode* inode,struct file* filp)
{
init_timer(&(timer_dev->timer_list));//初始化定时器
timer_dev->timer_list.function=timer_function;//设置定时器处理函数
timer_dev->timer_list.expires=jiffies+HZ;//处理函数1s后运行
add_timer(&timer_dev->timer_list);//添加定时器
atomic_set(&(timer_dev->count),0);
return 0;
}
//--------------------------------------

//----------------timer_read function---------------
static int timer_read(struct file* filp,char __user *buf,size_t count,loff_t* f_pos)
{

 unsigned int counter=atomic_read(&(timer_dev->count));
if(copy_to_user(buf,(unsigned int*)&counter,sizeof(unsigned int)))
  {
   printk("copy to user error\n");
   goto out;
  }
return (sizeof(unsigned int));
out:
return (-EFAULT);

}

struct file_operations timer_ops={
.owner=THIS_MODULE,
.open=timer_open,
.read=timer_read,
.release=timer_release,
};
static int __init timer_init(void)
{
 int ret;
 
 if(TIMER_MAJOR)//主设备号大于0,静态申请设备号
	{
	timer_dev_t=MKDEV(TIMER_MAJOR,TIMER_MINOR);
	ret=register_chrdev_region(TIMER_MAJOR,1,"timer_dev");//first,count,name
	}
 else
	{
	ret=alloc_chrdev_region(&timer_dev_t,0,1,"time_dev");
	timer_dev_major=MAJOR(timer_dev_t);
	}
 if(ret<0)
	{
	printk("can't get major %d\n",timer_dev_major);
	return ret;
	}
//-----------------------------------------------------------
 timer_dev=kmalloc(sizeof(struct TIMER_DEV),GFP_KERNEL); 
	memset(timer_dev,0,sizeof(struct TIMER_DEV));
 cdev_init(&(timer_dev->cdev),&timer_ops);
 cdev_add(&(timer_dev->cdev),timer_dev_t,1);
 printk("init timer_dev success\n");
return 0;


}
static void __exit timer_exit(void)
{
kfree(timer_dev);
cdev_del(&(timer_dev->cdev));
unregister_chrdev_region(MKDEV(TIMER_MAJOR,0),1);
}
module_init(timer_init);
module_exit(timer_exit);
需要手动创建设备节点,mknod /dev/timer_dev c 120 0
测试程序:
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <fcntl.h>
int main()
{
int fd;
int i;
int counter=0;
int old_counter=0;
fd=open("/dev/timer_dev",O_RDWR);
if(fd<0)
{
printf("open file error\n");
exit(1);
}
for(i=0;i<30;)//运行30s
  {
  read(fd,&counter,sizeof(int));
 if(counter!=old_counter)
    {
     printf("second=%d\n",counter);
     old_counter=counter;
    i++;
    }

  }
close(fd);
exit (0);

}
测试结果 添加模块后使用dmesg查看内核信息
[ 1239.176994] current jiffies is 235468,count=123
[ 1240.174459] current jiffies is 235718,count=124
[ 1241.171920] current jiffies is 235968,count=125
[ 1242.169383] current jiffies is 236218,count=126

测试程序的结果
second=1
second=2
second=3
second=4
second=5
second=6
second=7
second=8
second=9
second=10
second=11


  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值