新闻中心

EEPW首页 > 嵌入式系统 > 设计应用 > linux驱动之内核定时器驱动设计

linux驱动之内核定时器驱动设计

作者: 时间:2016-12-01 来源:网络 收藏
驱动程序:
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
/*采用宏定义设置设备的主设备号*/
#define SECOND_MAJOR 0
/*静态的分别保存静态主设备号的变量*/
static int second_major = SECOND_MAJOR;
/*设备结构体,通常在设备中包含需要的设备,比如字符、块等类型*/
struct second_dev{
/*添加设备类型,
我认为可以采用一个联合体,
包含块设备或者字符设备,类似inode的实现方法,
这样可以提高结构体的通用性
*/
struct cdev cdev;
/*原子变量,用来统计*/
atomic_t counter;
/*添加内核定时器结构体变量*/
struct timer_list s_timer;
/*用于动态创建设备文件的设备类*/
struct class *myclass;
};
/*结构体指针或者采用全局变量直接定义结构都可以*/
struct second_dev *second_devp;
/*如果定时时间到了,定时器的处理函数*/
static void second_timer_handler(unsigned long arg)
{
/*
修改定时器中的到期时间,增加时间为1s,
需要注意的是mod_timer函数是重新注册定时器到内核
而不管定时器是否被运行过
*/
mod_timer(&second_devp->s_timer,jiffies + HZ);
/*原子变量的增加*/
atomic_inc(&second_devp->counter);
/*输出jiffies值*/
printk(KERN_NOTICE "Current jiffies is %d",jiffies);
}
/*open函数实现*/
static int second_open(struct inode *inode,struct file *filp)
{
/*初始化定义的内核定时器*/
init_timer(&second_devp->s_timer);
/*指定内核定时器的处理函数是上面定义好的函数*/
second_devp->s_timer.function = second_timer_handler;
/*指定定时间隔是1s*/
second_devp->s_timer.expires = jiffies + HZ;
/*将定时器添加到内核*/
add_timer(&second_devp->s_timer);
/*同时设备相关的统计值为0*/
atomic_set(&second_devp->counter,0);
return 0;
}
/*release函数的实现*/
static int second_release(struct inode *inode,struct file *filp)
{
/*如果没有到时间就关闭设备,直接删除定时器*/
del_timer(&second_devp->s_timer);
return 0;
}
/*read函数的实现*/
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);
/*
采用put_user实现数值的传送
put_user函数存在对指针变量的检查,
因此不需要检测指针是否正确
*/
if(put_user(counter,(int *)buf))
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 int __init second_init(void)
{
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_devp->myclass = class_create(THIS_MODULE,"second_timer_class");
/*字符设备初始化,绑定相关操作到设备*/
cdev_init(&second_devp->cdev,&second_fops);
/*设备的拥有者*/
second_devp->cdev.owner = THIS_MODULE,
/*添加设备到内核*/
ret = cdev_add(&second_devp->cdev,devno,1);
/*错误处理*/
if(ret)
{
printk(KERN_NOTICE "ERROR %d",ret);
goto fail_malloc;
}
/*依据以前创建的设备类,创建设备*/
device_create(second_devp->myclass,NULL,devno,NULL,"second%d",0);
return 0;
/*错误操作*/
fail_malloc:
unregister_chrdev_region(devno,1);
return ret;
}
/*退出函数*/
static void __exit second_exit(void)
{
/*释放设备*/
device_destroy(second_devp->myclass,MKDEV(second_major,0));
/*删除字符设备*/
cdev_del(&second_devp->cdev);
/*释放设备类*/
class_destroy(second_devp->myclass);
/*释放分配的内存空间大小*/
kfree(second_devp);
/*释放设备号*/
unregister_chrdev_region(MKDEV(second_major,0),1);
}
/*卸载和加载*/
module_init(second_init);
module_exit(second_exit);
/*LICENSE和作者信息*/
MODULE_LICENSE("GPL");
MODULE_AUTHOR("GP-");
应用程序:
#include
#include
#include
#include
#include
#include
#include
int main()
{
int fd;
int counter = 0;
int old_counter = 0;
fd = open("/dev/second0",O_RDONLY);
if(fd != -1)
{
while(1)
{
read(fd,&counter,sizeof(unsigned int));
if(counter != old_counter)
{
printf("second after open /dev/second0 : %d",counter);
old_counter = counter;
}
}
}
else
{
printf("Device open failure");
exit(1);
}
exit(0);
}
实验效果:
[root@EmbedSky Test]# ./app-timer
Current jiffies is 2137721
second after open /dev/second0 : 1
Current jiffies is 2137921
second after open /dev/second0 : 2
Current jiffies is 2138121
second after open /dev/second0 : 3
Current jiffies is 2138321
second after open /dev/second0 : 4
Current jiffies is 2138521
second after open /dev/second0 : 5
Current jiffies is 2138721
second after open /dev/second0 : 6
以上的结果表明内核定时器基本实现了效果,但从实验结果看好像为每两秒实现一次显示。具体的原因还有待于再次分析,因为arm中的HZ应该为100,而不是200。
上一页 1 2 下一页

评论


技术专区

关闭