linux驅動之內核定時器驅動設計
驅動程序:
#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
主站蜘蛛池模板:
方城县|
洛宁县|
霸州市|
裕民县|
镇坪县|
无锡市|
鄯善县|
鹰潭市|
龙胜|
出国|
霍林郭勒市|
延安市|
天津市|
深泽县|
辛集市|
石泉县|
博罗县|
喜德县|
益阳市|
新干县|
杭州市|
巴林左旗|
慈溪市|
延安市|
仪征市|
石景山区|
夹江县|
乡宁县|
金乡县|
张北县|
郯城县|
镇安县|
通化市|
两当县|
乌兰浩特市|
宝兴县|
丹寨县|
曲麻莱县|
卢龙县|
曲沃县|
沙田区|
評論