内核定时器的使用

本文介绍了一个简单的Linux内核定时器模块的实现过程,包括模块代码、Makefile配置、加载脚本及应用程序示例。该模块通过定时器周期性地更新计数器,并允许用户空间程序读取计数值。

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

1.内核模块代码

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

int timer_open(struct inode *, struct file *);
int timer_release(struct inode *, struct file *);
ssize_t timer_read(struct file *, char __user *, size_t, loff_t *);
ssize_t timer_write(struct file *, char __user *, size_t, loff_t *);
loff_t timer_llseek(struct file *, loff_t, int);
int timer_ioctl(struct file *, unsigned int, unsigned long);

#define N 100
#define CLEAR_DATA 1

struct timer_dev{
    struct cdev cdev;
    struct timer_list timer;
    atomic_t counter;
};

struct file_operations timer_fops = {
    .owner = THIS_MODULE,
    .llseek = timer_llseek,
    .open = timer_open,
    .release = timer_release,
    .unlocked_ioctl = timer_ioctl,
    .read = timer_read,
    .write = timer_write,
};

dev_t dev_num;
struct timer_dev *dev;

void timer_func(unsigned long data)
{
    mod_timer(&dev->timer, jiffies + HZ);
    atomic_inc(&dev->counter);

    return ;
}

int timer_open(struct inode *inodep, struct file *filp)
{
    init_timer(&dev->timer);
    dev->timer.function = timer_func;
    dev->timer.expires = jiffies + HZ;

    add_timer(&dev->timer);

    return 0;
}

int timer_release(struct inode *inodep, struct file *filp)
{
    del_timer(&dev->timer);

    return 0;
}

ssize_t timer_read(struct file *filp, char __user *buf, size_t len, loff_t *fpos)
{
    int counter;

    counter = atomic_read(&dev->counter);
    if(put_user(counter, (int *)buf) < 0)
    {
        return -EFAULT;
    }

    return sizeof(int);
}

ssize_t timer_write(struct file *filp, char __user *buf, size_t len, loff_t *fpos)
{
    return 0;
}

loff_t timer_llseek(struct file *filp, loff_t off, int whence)
{
    return 0;
}

int timer_ioctl(struct file *filp, unsigned int cmd, unsigned long val)
{
    return 0;
}


static int __init timer_init(void)
{
    if(alloc_chrdev_region(&dev_num, 0, 1, "timer"))
        return -EFAULT;

    dev = kzalloc(sizeof(struct timer_dev), GFP_KERNEL);

    cdev_init(&dev->cdev, &timer_fops);
    dev->cdev.owner = THIS_MODULE;
    dev->cdev.ops = &timer_fops;

    int err = cdev_add(&dev->cdev, dev_num, 1);

    if(err)
        goto fail;

    printk("timer_init is success\n");
    return 0;

fail:
    kfree(dev);
    return err;
}

static void __exit timer_exit(void)
{    
    unregister_chrdev_region(dev_num, 1);

    cdev_del(&dev->cdev);

    kfree(dev);

    printk("timer_exit is success\n");

    return ;
} 


MODULE_LICENSE("GPL");

module_init(timer_init);
module_exit(timer_exit);

2.Makefile文件

TARGET= timer

obj-m := ${TARGET}.o

CURRENT_PATH := $(shell pwd)

LINUX_KERNEL := $(shell uname -r)

LINUX_KERNEL_PATH := /usr/src/linux-headers-${LINUX_KERNEL}

.PHONY: all
.PHONY: clean
.PHONY: install
.PHONY: remove

all:
    make -C $(LINUX_KERNEL_PATH) M=$(CURRENT_PATH) modules

clean:
    make -C $(LINUX_KERNEL_PATH) M=$(CURRENT_PATH) clean

install:
    sudo ./${TARGET}.sh

remove:
    sudo ./clean.sh

3. timer.sh 脚本

#!/bin/sh

module="timer"
mode="666"

/sbin/insmod ${module}.ko || exit 1

rm -f /dev/${module}

major=$(awk 'BEGIN{count = 0;} {if($2 == module && count == 0) {print $1; count++;} }' module=$module /proc/devices)

mknod /dev/${module} c $major 0

chmod $mode /dev/${module}

4. clean.sh脚本

#!/bin/bash

module="timer"

/sbin/rmmod ${module} || exit 1

rm -f /dev/${module}

5.应用程序的使用:

#include <errno.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>

int main(int argc, char *argv[])
{
    int fd;

    if((fd = open("/dev/timer", O_RDWR)) < 0)
        goto fail;

    int counter = 0, old_counter = 0;

    while(1)
    {
        if(read(fd, &counter, sizeof(counter)) < 0)
            goto fail;

        if(counter != old_counter)
            printf("counter = %d\n", counter);

        old_counter = counter;
    }

    return 0;

fail:
    printf("read_timer error: %s\n", strerror(errno));
    exit(1);
}

本文引述自 http://edsionte.com/techblog/archives/1738

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值