《Linux设备驱动开发详解上的秒字符设备》定时中断

内核定时器编程

实质上,时钟中断处理程序执行Update_process_timers()函数,该函数调用run_local_timers()函数,这个函数处理TIMER_SOFTIRQ软中断,运行当前处理器上到期的所有定时器。

Linux内核所提供的用于操作定时器的数据结构和函数如下:

1、time_list     //在linux内核中,time_list结构体的一个实例对应一个定时器。

    struct timer_list{

               struct list_head entry;

               unsigned long expires;

               void (*function)(unsigned long);

               unsigned long data;

               struct timer_base_s *base;

      }

      struct timer_list my_timer;

2、初始化定时器

     void init_timer(struct timer_list *timer);

3、增加定时器

     void add_timer(struct timer_list *timer);

4、删除定时器

     int del_timer(struct timer_list *timer);


#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/init.h>
#include <linux/fs.h>
#include <linux/cdev.h>
#include <linux/uaccess.h>
#include <linux/timer.h>
#include <asm/atomic.h>


#define SECOND_MAJOR 250

static int second_major=SECOND_MAJOR;

struct second_dev{
	struct cdev cdevp;
	atomic_t counter;
	struct timer_list s_timer;
/*
struct timer_list{
	struct list_head list;
	unsigned long expires; 
	unsigned long data;  //device ID ,or something else
	void (*function)(unsigned long); //when the timer is overfloat,the function will be executed
};
*/
};

struct second_dev *second_devp;

static void second_timer_handle(unsigned long arg){
	mod_timer(&second_devp->s_timer,jiffies+HZ);//insert list 
	atomic_inc(&second_devp->counter); //counter+=1;
	printk("current jiffies is %ld\n",jiffies);
	/*全局变量jiffies用来记录自系统启动以来产生的节拍的总数。
	启动时,内核将该变量初始化为0,此后,每次时钟中断处理程序都会增加该变量的值。
	一秒内时钟中断的次数等于Hz,所以jiffies一秒内增加的值也就是Hz。*/
}

static int second_open(struct inode *inode,struct file *filp){
	printk("now open the second char device .");
	printk("the seconds is %d.",second_devp->counter);
	/*初始化定时器*/
	init_timer(&second_devp->s_timer); 
	second_devp->s_timer.function=&second_timer_handle;
	second_devp->s_timer.expires=jiffies+HZ;
	/*添加(注册)定时器*/
	add_timer(&second_devp->s_timer);

	atomic_set(&second_devp->counter,0);
	return 0;
}

int second_release(struct inode *inode,struct file *filp){
	/*删除定时器*/
	del_timer(&second_devp->s_timer);
	return 0;
}

static ssize_t second_read(struct file *filp,char __user *buf,size_t count,loff_t *ppos){
	int counter;
	counter=atomic_read(&second_devp->counter);
	if(copy_to_user(buf,&counter,0x4))
	   return -EFAULT;
	else return sizeof(unsigned int);
}

static const struct file_operations second_fops={
	.owner=THIS_MODULE,
	.open=second_open,
	.release=second_release,
	.read=second_read,
};


static void second_setup_cdev(struct second_dev *second_devp,int index){
	int err,devno=MKDEV(second_major,index);
	cdev_init(&second_devp->cdevp,&second_fops);
	second_devp->cdevp.owner=THIS_MODULE;
	second_devp->cdevp.ops=&second_fops;
	err=cdev_add(&second_devp->cdevp,devno,1);
	if(err)
	   printk("add the second cdev failly");
}

int __init second_init(){
	int ret;
	dev_t devno=MKDEV(second_major,0);
	if(second_major)
	  ret=register_chrdev_region(devno,1,"second");
	else 
	{
		ret=alloc_chrdev_region(&devno,0,1,"second");
		second_major=MAJOR(devno);	
	}
	if(ret<0)
	  return ret;
	second_devp=kmalloc(sizeof(struct second_dev),GFP_KERNEL);
	if(!second_devp){
		ret=-ENOMEM;
		goto fail_malloc;
	}
	memset(second_devp,0,sizeof(struct second_dev));
	second_setup_cdev(second_devp,0);
	return 0;
	fail_malloc:unregister_chrdev_region(devno,1);
}

void second_exit(void)
{
	cdev_del(&second_devp->cdevp);
	kfree(second_devp);
	unregister_chrdev_region(MKDEV(second_major,0),1);
}

MODULE_AUTHOR("wang quan");
MODULE_LICENSE("Dual BSD/GPL");

module_param(second_major,int,S_IRUGO);

module_init(second_init);
module_exit(second_exit);

	 



  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值