linux内核定时器编程

版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://blog.csdn.net/jeason29/article/details/48494867

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

1)struct timer_list 一个struct timer_list对应了一个定时器。
#include <linux/timer.h>
以下列出常用的接口:
struct timer_list
  {
   /*....*/
   unsigned long expires;//定时器服务函数开始执行时间
   void (*function)(unsigned long);//定义一个指向定时器服务函数的指针function,服务函数有一个 unsigned long的参数,并且返回void
   unsigned long data;//定时时间到时,data参数会传入服务函数
  }
 
void init_timer(struct timer_list* timer)//初始化一个定时器

-----------使用定时器的步骤--------------
struct timer_list  my_timer_list;//定义一个定时器,可以把它放在你的设备结构中 struct{定义一个定时器}
init_timer(&my_timer_list);//初始化一个定时器
my_timer_list.expire=jiffies+HZ;//定时器1s后运行服务程序
my_timer_list.function=timer_function;//定时器服务函数
add_timer(&my_timer_list);//添加定时器
void timer_function(unsigned long)//写定时器服务函数
del_timer(&my_timer_list);//当定时器不再需要时删除定时器
del_timer_sync(&my_timer_list);//基本和del_timer一样,比较适合在多核处理器使用,一般推荐使用del_timer_sync
-------------------------------------------------
2.以下是一个定时1s的驱动程序
[cpp]
  1. #include <linux/miscdevice.h>  
  2. #include <linux/delay.h>  
  3. #include <asm/irq.h>  
  4. //#include <mach/regs-gpio.h>  
  5. //#include <mach/hardware.h>  
  6. #include <linux/kernel.h>  
  7. #include <linux/module.h>  
  8. #include <linux/init.h>  
  9. #include <linux/mm.h>  
  10. #include <linux/fs.h>  
  11. #include <linux/types.h>  
  12. #include <linux/delay.h>  
  13. #include <linux/moduleparam.h>  
  14. #include <linux/slab.h>  
  15. #include <linux/errno.h>  
  16. #include <linux/ioctl.h>  
  17. #include <linux/cdev.h>  
  18. #include <linux/string.h>  
  19. #include <linux/list.h>  
  20. #include <linux/pci.h>  
  21. #include <asm/uaccess.h>  
  22. #include <asm/atomic.h>  
  23. #include <asm/unistd.h>  
  24. #include <asm/io.h>  
  25. #include <asm/system.h>  
  26. #include <asm/uaccess.h>  
  27. #define TIMER_MAJOR 300  
  28. #define TIMER_MINOR 0  
  29. dev_t timer_dev_t;//设备号  
  30. dev_t timer_dev_major=TIMER_MAJOR;  
  31. dev_t timer_dev_minor=TIMER_MINOR;  
  32. struct TIMER_DEV  
  33. {  
  34.   struct cdev cdev;  
  35.   atomic_t count;  
  36.   struct timer_list timer_list;  
  37.   
  38. };  
  39. struct TIMER_DEV* timer_dev;  
  40. //---------timer interrupt function定时器中断函数----------------  
  41. static void timer_function(unsigned long data)  
  42. {  
  43. mod_timer(&(timer_dev->timer_list),jiffies+HZ);//重新设置时间  
  44. printk("current jiffies is %ld,count=%d\n",jiffies,timer_dev->count);  
  45. //(timer_dev->count)++;  
  46. atomic_inc(&(timer_dev->count));  
  47. }  
  48. //--------timer release function定时器发布函数--------------------  
  49. static int timer_release(struct inode* inode, struct file* filp)  
  50. {  
  51. del_timer_sync(&(timer_dev->timer_list));  
  52. return 0;  
  53. }  
  54.   
  55. //----------------file open function文件打开函数-----------------  
  56. static int timer_open(struct inode* inode,struct file* filp)  
  57. {  
  58. init_timer(&(timer_dev->timer_list));//初始化定时器  
  59. timer_dev->timer_list.function=timer_function;//设置定时器处理函数  
  60. timer_dev->timer_list.expires=jiffies+HZ;//处理函数1s后运行  
  61. add_timer(&timer_dev->timer_list);//添加定时器  
  62. atomic_set(&(timer_dev->count),0);  
  63. return 0;  
  64. }  
  65. //--------------------------------------  
  66.   
  67. //----------------timer_read function文件读取函数---------------  
  68. static int timer_read(struct file* filp,char __user *buf,size_t count,loff_t* f_pos)  
  69. {  
  70.   
  71.  unsigned int counter=atomic_read(&(timer_dev->count));  
  72. if(copy_to_user(buf,(unsigned int*)&counter,sizeof(unsigned int)))  
  73.   {  
  74.    printk("copy to user error\n");  
  75.    goto out;  
  76.   }  
  77. return (sizeof(unsigned int));  
  78. out:  
  79. return (-EFAULT);  
  80.   
  81. }  
  82.   
  83. struct file_operations timer_ops={  
  84. .owner=THIS_MODULE,  
  85. .open=timer_open,  
  86. .read=timer_read,  
  87. .release=timer_release,  
  88. };  
  89. static int __init timer_init(void)  
  90. {  
  91.  int ret;  
  92.    
  93.  if(TIMER_MAJOR)//主设备号大于0,静态申请设备号  
  94.     {  
  95.     timer_dev_t=MKDEV(TIMER_MAJOR,TIMER_MINOR);  
  96.     ret=register_chrdev_region(TIMER_MAJOR,1,"timer_dev");//first,count,name  
  97.     }  
  98.  else  
  99.     {  
  100.     ret=alloc_chrdev_region(&timer_dev_t,0,1,"time_dev");  
  101.     timer_dev_major=MAJOR(timer_dev_t);  
  102.     }  
  103.  if(ret<0)  
  104.     {  
  105.     printk("can't get major %d\n",timer_dev_major);  
  106.     return ret;  
  107.     }  
  108. //-----------------------------------------------------------  
  109.  timer_dev=kmalloc(sizeof(struct TIMER_DEV),GFP_KERNEL);   
  110.     memset(timer_dev,0,sizeof(struct TIMER_DEV));  
  111.  cdev_init(&(timer_dev->cdev),&timer_ops);  
  112.  cdev_add(&(timer_dev->cdev),timer_dev_t,1);  
  113.  printk("init timer_dev success\n");  
  114. return 0;  
  115.   
  116.   
  117. }  
  118. static void __exit timer_exit(void)  
  119. {  
  120. kfree(timer_dev);  
  121. cdev_del(&(timer_dev->cdev));  
  122. unregister_chrdev_region(MKDEV(TIMER_MAJOR,0),1);  
  123. }  
  124. module_init(timer_init);  
  125. module_exit(timer_exit);  
测试程序
[cpp]
  1. #include <stdio.h>  
  2. #include <stdlib.h>  
  3. #include <unistd.h>  
  4. #include <fcntl.h>  
  5. int main()  
  6. {  
  7. int fd;  
  8. int i;  
  9. int counter=0;  
  10. int old_counter=0;  
  11. fd=open("/dev/timer_dev",O_RDWR);  
  12. if(fd<0)  
  13. {  
  14. printf("open file error\n");  
  15. exit(1);  
  16. }  
  17. for(i=0;i<30;)//运行30s  
  18.   {  
  19.   read(fd,&counter,sizeof(int));  
  20.  if(counter!=old_counter)  
  21.     {  
  22.      printf("second=%d\n",counter);  
  23.      old_counter=counter;  
  24.     i++;  
  25.     }  
  26.   
  27.   }  
  28. close(fd);  
  29. exit (0);  
  30.   
  31. }  
/*补充:定时器的到期时间往往在目前的jifies的基础上添加一个时延,若为HZ,则表示延迟1S*/
测试结果 添加模块后使用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
展开阅读全文

linux内核定时器

06-24

我做的程序需要两个定时器,一个用于自动备份,一个用于自动清理所以我觉得用alarm()的话,统一发送SIG_ALRM信号是不行的,所以我采用了struct timer_list和add_timer机制,但是发现要包含linux/timer.h,所以不得不改用模块编程(正好可以深入一下内核),可是发现在内核里包含time.h并调用localtime(),mktime()等函数都不行,后来又改包含linux/time.h,发现那个里面的函数跟time.h不一样,请各位指点一下怎样做。rnrn另外,我对内核模块的编译也很迷糊,希望各位大侠可以耐心指点一下。不胜感谢。我的模块代码和makefile如下,请指正:rnrn#include rn#include rn#include rn#include rn#include rnrnstatic int backup_time=0; //模块参数,自动备份时间rnstatic int clean_time=0; //模块参数,自动清理时间rnstruct timer_list backup_timer[2]; //全局变量,两个计时器rnint DB_BACKUP()rnrn return 0;rnrnrnint DB_CLEAN()rnrn return 0;rnrnrn//自动备份函数rnvoid auto_backup(unsigned long data)rn rn struct timeval hour;rn hour.tv_sec=86400;rn hour.tv_usec=0;rn int jiffies_t=tvtojiffies(&hour);rnrn //设置第一个计时器rn backup_timer[0].expires=jiffies_t;rn backup_timer[0].data=1;rn backup_timer[0].function=DB_BACKUP;rn add_timer(&backup_timer[0]);rnrn //实现备份功能 rn DB_BACKUP();rnrn return;rnrnrn//自动清理rnvoid auto_clean(unsigned long data)rnrn struct timeval hour;rn hour.tv_sec=86400;rn hour.tv_usec=0;rn int jiffies_t=tvtojiffies(&hour);rnrn //设置自动清理定时器rn backup_timer[1].expires=jiffies_t;rn backup_timer[1].data=0;rn backup_timer[1].function=DB_CLEAN;rn add_timer(&backup_timer[1]);rnrn DB_CLEAN();rnrn return;rnrnrn//初始化两个定时器rnint set_backup_timer()rnrn printk(KERN_ALERT "Auto Backup:%d,Auto Clean:%d",backup_time,clean_time);rnrn struct tm tm_v;rn time_t time1,time2;rn struct timeval hour;rn hour.tv_usec=0;rn time1=time(NULL); //姹傚嚭褰撳墠鏃堕棿rn memcpy((char *)&tm_v,(char *)localtime(&time1),sizeof(struct tm)); rn tm_v.tm_min=0;rn tm_v.tm_sec=0; //鍚屼笂rnrn tm_v.tm_hour=backup_time;rn time2=mktime(&tm_v);rn if((hour.tv_sec=difftime(time2,time1))<0)rn rn hour.tv_sec+=86400;rn rn int jiffies_t=tvtojiffies(&hour);rnrn //浠ヤ笅鏄嚜鍔ㄥ浠藉畾鏃跺櫒rn del_timer(&backup_timer[0]);rn backup_timer[0].expires=jiffies_t;rn backup_timer[0].data=0;rn backup_timer[0].function=auto_backup;rn add_timer(&backup_timer[0]);rnrn //姹傚嚭浠庡綋鍓嶆椂闂寸偣鍒扮涓€娆¤嚜鍔ㄥ浠界殑鏃堕棿锛屽苟杞寲鎴恓iffies鏁?rn tm_v.tm_hour=clean_time;rn time2=mktime(&tm_v);rn if((hour.tv_sec=difftime(time2,time1))<0)rn rn hour.tv_sec+=86400;rn rn jiffies_t=tvtojiffies(&hour);rnrn //浠ヤ笅鏄嚜鍔ㄥ浠藉畾鏃跺櫒rn del_timer(&backup_timer[1]);rn backup_timer[1].expires=jiffies_t;rn backup_timer[1].data=0;rn backup_timer[1].function=auto_clean;rn add_timer(&backup_timer[1]);rnrn return 0;rnrnrnstatic int __init backup_init(void)rnrn init_timer(&backup_timer[0]);rn init_timer(&backup_timer[1]);rnrn //初始化定时器rn set_backup_timer(); rnrn return 0;rnrnrnstatic void __exit backup_exit(void)rnrn del_timer(&backup_timer[0]);rn del_timer(&backup_timer[1]);rnrn return;rnrnrnmodule_init(backup_init);rnmodule_exit(backup_exit);rnrnrnrnrnrnrnMAKEFILE:rnrnifneq ($(KERNELRELEASE),)rn obj-m := backup_timer.ornelsern KDIR := /lib/modules/$(shell uname -r)/buildrn PWD := $(shell pwd)rnrndefault:rn $(MAKE) -C $(KDIR) M=$(PWD) modules -I/usr/src/rnclean:rn rm -f *.ko *.mod.c *.orninstall:rn insmod hook.kornuninstall:rn rmmod hook.kornendifrnrnrnrnrn 论坛

Linux内核信号量和定时器问题请教:

01-14

rn正在学习用户态线程和内核态定时器的使用,有个问题请教大家:rnrn我在用户空间建立了一个线程,内核做一个字符驱动模块,通过ioctl调用来不断读取内核定时器有没有rnrn到期。在设备结构体里面加了一个信号量,在open调用的时候把信号量拿到,使用一个内核定时器,在内rnrn核定时器到期的处理函数里面释放信号量,这样用户线程调ioctl的时候就获取不到信号量了,等定时器rnrn超时了,就会释放信号量,这样ioctl就返回到用户空间了,可是下次再调用ioctl的时候就不等待信号量了,不知道为什么??rnrn不知道这样做行不行,看书上好像都是两个内核线程间用信号量来通信,请大家指教,谢谢!rnrnvoid timer_handle(void)rnrn int i = 0;rn mod_timer(&KDA_devp->s_timer,jiffies + HZ * 5); /*重新改变定时器的超时时间*/ rn up(&KDA_devp->sem); /*释放信号量,ioctl调用可以获取到该信号量*/rnrnrnrnint KDA_open(struct inode *inode, struct file *filp)rnrn rn struct KDA_dev *dev; /* device information */rnrn dev = container_of(inode->i_cdev, struct KDA_dev, cdev);rn filp->private_data = dev; /* for other methods */rn rn init_timer(&KDA_devp->s_timer);rn KDA_devp->s_timer.function = &timer_handle;rn KDA_devp->s_timer.expires = jiffies + HZ * 5;rn add_timer(&KDA_devp->s_timer); /*添加(注册)定时器*/rn down_interruptible(&dev->sem); /*获取信号量*/rn rn return 0;rnrnrnrnrnint KDA_ioctl(struct inode *inode, struct file *filp,rn unsigned int cmd, unsigned long arg)rnrn int err = 0;rn int isr_num = 100;rn rn struct KDA_dev *dev = filp->private_data; rn rn printk("want to get sem \n");rn rn down_interruptible(&dev->sem);rn rn switch(cmd)rn rn case 1 :rn printk("the case 1 \n");rn break;rn rn case 2 :rn printk("the case 2 \n"); rn break;rn rn case 3 :rn __put_user(KDA_devp->ISR_flag, (int __user *)arg); rn break; rn default:rn printk("the default case \n"); rn rn rn 论坛

没有更多推荐了,返回首页