使用内核定时器的second字符设备驱动

second.c:


#include<linux/kernel.h>
#include<linux/module.h>
#include<linux/fs.h>  //file_operations
#include<linux/types.h> //dev_t
#include<linux/cdev.h>
#include<linux/slab.h> //kcalloc
#include<linux/uaccess.h> //copy_to_user,copy_from_user
#include<linux/interrupt.h>//中断
#include<linux/timer.h>

#define SECOND_MAJOR 112

static int second_major = SECOND_MAJOR;

//second设备结构体
struct second_dev{
    struct cdev cdev;
    atomic_t counter; //一共经历了多少秒
    struct timer_list s_timer;  //设备要使用的定时器
};

struct second_dev *second_devp;

//定时器处理函数
static void second_timer_handle(unsigned long arg){
    mod_timer(&second_devp->s_timer,jiffies + HZ);  //修改定时器的到期时间
    atomic_inc(&second_devp->counter);  //经历时间+1秒
    printk(KERN_NOTICE "current jiffies is %ld\n",jiffies);
}

//文件打开函数
int second_open(struct inode *inode,struct file *filp){
    //初始化定时器
    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); //atomic原子
    //相对于copy_to_user和copy_from_user,这两个函数主要用于完成一些简单类型变量(char、int、long等)的拷贝任务
    //对于一些复合类型的变量,比如数据结构或者数组类型,get_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,
};

//初始化并注册cdev
static void second_setup_cdev(struct second_dev *dev,int index){
    int err,devno = MKDEV(second_major,index);

    cdev_init(&dev->cdev,&second_fops); //cdev初始化并关联fops
    dev->cdev.owner = THIS_MODULE;
    dev->cdev.ops = &second_fops;
    err = cdev_add(&dev->cdev,devno,1);  //添加设备
    if(err)
        printk(KERN_NOTICE "error %d adding %d",err,index);
}

//设备驱动模块加载函数
static __init int second_init(void){ //必须有void !!!!!
    int ret;
    dev_t devno = MKDEV(second_major,0); //此设备号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);
    return ret;
}

//模块卸载函数
void second_exit(void){  //必须要有void !!!!!!!!!
    cdev_del(&second_devp->cdev);  //删除设备
    kfree(second_devp);
    unregister_chrdev_region(MKDEV(second_major,0),1);
}

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

module_param(second_major,int,S_IRUGO);

module_init(second_init);
module_exit(second_exit);



test_second.c:



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

int main(){
    int fd;
    int counter=0;
    int old_counter = 0;

    //打开/dev/second设备文件
    fd = open("/dev/second",O_RDONLY);
    if(fd != -1){
        while(1){
            read(fd,&counter,sizeof(unsigned int));
            if(counter != old_counter){
                printf("seconds after open /dev/second :%d\n",counter);
                old_counter = counter;
            }
        }
    }else  printf("device open failure\n");
    close(fd);
}

以上代码在3内核版本中测试通过


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值