linux 内核定时器

这篇博客详细介绍了如何在Linux内核中实现一个基于`jiffies`和`timer_list`结构的定时器。通过示例代码展示了从创建设备节点、初始化定时器到注册设备驱动的完整过程,并提供了一个验证程序来读取定时器计数值。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

节拍率 : 系统定时器以某种频率触发时钟中断 , 这个频率就称为节拍率 ( tick rate ) 。 节拍率是通过静态预处理定义的,被定义为 HZ 。1HZ的时间为1秒
节拍 :两次时钟中断的间隔就称为节拍( tick ) 。可以看到,节拍等于节拍率分之一。

jiffies: 全局变量 jiffies 用来记录系统自启动以来产生的节拍总数 。 通过 jiffies/HZ 就可获取系统自启动以来的秒数。

/* pc下驱动, arm开发板上驱动要添加<linux/kernel.h> 等头文件*/

#include <linux/module.h>
#include <linux/slab.h>
#include <linux/types.h>
#include <linux/fs.h>
#include <linux/errno.h>
#include <linux/mm.h>
#include <linux/sched.h>
#include <linux/moduleparam.h>
#include <linux/init.h>
#include <linux/cdev.h>
#include <linux/device.h>
#include <asm/io.h>
#include <asm/system.h>
#include <asm/uaccess.h>

struct sec_dev
{
struct cdev cdev;
atomic_t count;
struct timer_list s_timer;
};

static int sec_major = 0;
static struct sec_dev *sec_devp;
static struct class *sec_class;
static struct device *sec_device;

static void sec_timer_handle(unsigned long arg)
{
mod_timer(&sec_devp->s_timer, jiffies+HZ);
atomic_inc(&sec_devp->count);
}

static int sec_open(struct inode *inode, struct file *filp)
{
struct sec_dev *devp;

devp = container_of(inode->i_cdev, struct sec_dev, cdev);
filp->private_data= devp;
init_timer(&devp->s_timer);
devp->s_timer.function = sec_timer_handle;
devp->s_timer.expires = jiffies + HZ;
add_timer(&devp->s_timer);
atomic_set(&devp->count, 0);
return 0;
}

static int sec_release(struct inode *inode, struct file *filp)
{
del_timer(&sec_devp->s_timer);
return 0;
}

static ssize_t sec_read(struct file *filp, const char __user *buf, size_t size, loff_t *fops)
{
struct sec_dev *devp = filp->private_data;
int counts;

counts = atomic_read(&devp->count);
if(put_user(counts, (int *)buf)
return -EFAULT;
else
return sizeof(int);
}

static struct file_operations sec_fops =
{
.owner = THIS_MODULE,
.read = sec_read,
.open = sec_open,
.release = sec_release,
};

static void sec_setup_cdev(struct sec_dev *devp, int index)
{
int err;
dev_t dev = MKDEV(sec_major, index);

cdev_init(&devp->cdev, &sec_fops);
devp->cdev.owner = THIS_MODULE;
devp->cdev.ops = &sec_fops;
err = cdev_add(&devp->cdev, dev, 1);
if(err)
printk(KERN_NOTICE "ERROR %d adding sec_timer 0", err);
}

static int __init sec_init(void)
{
int result;
dev_t dev;

if(sec_major)
{
dev = MKDEV(sec_major, 0);
result = register_chrdev_region(dev, 1, "TIMER");
}
else
{
result = alloc_chrdev_region(&dev, 0, 1, "TIMER");
sec_major = MAJOR(dev);
}

if(result < 0)
return result;

sec_devp = kmalloc(sizeof(struct sec_dev), GFP_KERNEL);
if(sec_devp == NULL)
{
result = -ENOMEM;
goto fail;
}
memset(sec_devp, 0, sizeof(struct sec_dev));
sec_setup_cdev(sec_devp, 0);
sec_class = class_create(THIS_MODULE, "sec_timer");
if(IS_ERR(sec_class))
{
printk(KERN_NOTICE "can't create sec_class");
goto fail;
}
sec_device = device_create(sec_class, NULL, dev, NULL, "sec_timer");

return 0;
fail:
unregister_chrdev_region(dev, 1);
return result;
}

static void __exit sec_exit(void)
{
cdev_del(&sec_devp->cdev);
kfree(sec_devp);
device_destroy(sec_class, MKDEV(sec_major, 0));
class_destroy(sec_class);
unregister_chrdev_region(MKDEV(sec_major, 0), 1);
}

module_init(sec_init);
module_exit(sec_exit);

MODULE_AUTHOR("RIVER");
MODULE_LICENSE("Dual BSD/GPL");


/* 验证程序 */

#include <unistd.h>
#include <fcntl.h>
#include <stdio.h>                                                                                                                                                                                                             #include <stdlib.h>

int main(void)
{
int count = 0, old_count = 0;
int fd, test = 20;

fd = open("/dev/sec_timer", 0);
if(fd < 0)
{
fprintf(stderr, "can't open /dev/sec_timer\n");
exit(1);
}


while(test--)
{
read(fd, &count, sizeof(int));
if(count != old_count)
{
fprintf(stderr, "count after sec_timer %d\n", count);
old_count = count;
}
}
close(fd);
return 0;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值