使用内核定时器的second字符设备驱动及测试代码

驱动:

#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/fs.h>
#include <linux/init.h>
#include <linux/types.h>
#include <linux/errno.h>

#include <linux/cdev.h>//cdev
#include <linux/device.h>//udev
#include <linux/sched.h>//schedule
#include <linux/uaccess.h>//copy_to_user
#include <linux/slab.h>//kmalloc()

#define DEVICE_NAME "second_drv"
static int second_major=0;/*主设备号*/
struct class *second_class;

/*second设备结构体*/
static struct second_dev
{
    struct cdev cdev;/*cdev 结构体*/
    atomic_t counter;/*一共经历了多少时间;定义原子变量*/    
    struct timer_list s_timer;/*定义一个定时器*/
};
struct second_dev *second_devp;/*定义设备结构体指针*/

/*定时器处理函数*/
static void second_timer_handler(unsigned long arg)
{
    mod_timer(&second_devp->s_timer,jiffies+HZ);/*再次调度定时器*/
    atomic_inc(&second_devp->counter);/*counter 加1*/
    printk(KERN_NOTICE"current jiffies is %d!!\n",jiffies);
}

static int second_open(struct inode *inode, struct file *filp)
{
    //printk("in the second_open!!\n");
    filp->private_data=second_devp;/*将设备结构体指针赋值给文件私有数据指针*/

    /*初始化定时器*/
    init_timer(&second_devp->s_timer);
    second_devp->s_timer.function=&second_timer_handler;
    second_devp->s_timer.expires=jiffies+HZ;
    add_timer(&second_devp->s_timer);/*添加定时器*/

    atomic_set(&second_devp->counter,0);/*计数清零*/
    
    return 0;
}

static 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,ssize_t count,loff_t *ppos)
{    
    //printk("in the second_read!!\n");
    int counter;
    counter=atomic_read(&second_devp->counter);/*获取count值*/

    if(copy_to_user(buf,&counter,count))
        return -EFAULT;
    else 
        return sizeof(unsigned int);
}

static ssize_t second_write(struct file *filp,const char __user *buf,ssize_t count,loff_t *ppos)
{
    return 0;
}

/*文件操作结构体*/
static const struct file_operations second_fops={
    .owner = THIS_MODULE,
    .open  =second_open,
    .release =second_release,
    .read  =second_read,
    .write =second_write,
};

/*初始化并注册cdev*/
static void second_setup_cdev(struct second_dev *dev,int index)
{
    int err;
    dev_t devno=MKDEV(second_major,index);
    cdev_init(&dev->cdev,&second_fops);/*初始化cdev成员*/
    dev->cdev.owner=THIS_MODULE;
    err=cdev_add(&dev->cdev,devno,1);/*向系统注册字符设备*/
    if(err)
        printk(KERN_NOTICE"error=%d",err);
}

/*设备驱动模块加载函数*/
static int __init second_init(void)
{
    /*申请设备号*/
    int ret;
    dev_t devno=MKDEV(second_major,0);/*获得设备号*/
    if(second_major)
        ret=register_chrdev_region(devno,1,DEVICE_NAME);
    else
        {    
            /*动态申请设备号*/
            ret=alloc_chrdev_region(&devno,0,1,DEVICE_NAME);
            second_major=MAJOR(devno);
        }
    if(ret)
        {
            printk("request chrdev failed!!\n");
            return ret;
        }

    /*动态申请设备结构体内存*/
    second_devp=kmalloc(sizeof(struct second_dev),GFP_KERNEL);
    if(!second_devp)
        {
            ret= -ENOMEM;
            goto fail_kmalloc;
        }
    memset(second_devp,0,sizeof(struct second_dev));/*申请到的内存空间清零*/

    /*注册字符设备*/
    second_setup_cdev(second_devp,0);

    /*用udev机制自动创建设备文件结点*/
    second_class=class_create(THIS_MODULE,"second_class");/*在sys/class下添加second_class这个类*/
    if (IS_ERR(second_class)) 
    {
        printk(KERN_ERR "class_create() failed for second_class\n");
        goto fail_class_create;
    }
    device_create(second_class,NULL,devno,NULL,DEVICE_NAME);/*创建设备/dev/$DEVICE_NAME*/

    printk("init second_drv success!!,major=%d!!\n",second_major);
    return 0;
    fail_class_create:
        cdev_del(&second_devp->cdev);/*注销cdev*/
        kfree(second_devp);/*释放设备结构体内存*/
    fail_kmalloc:
        unregister_chrdev_region(devno,1);/*释放设备号*/
        
    return ret;
}

/*设备驱动模块卸载函数*/
static void __exit second_exit(void)
{
    device_destroy(second_class,MKDEV(second_major,0));/*注销设备*/
    class_destroy(second_class);/*注销类*/
    cdev_del(&second_devp->cdev);/*注销cdev*/
    kfree(second_devp);/*释放设备结构体内存*/
    unregister_chrdev_region(MKDEV(second_major,0),1);/*释放设备号*/
}

MODULE_AUTHOR("mhb@SEU");
MODULE_LICENSE("GPL");

module_init(second_init);
module_exit(second_exit);


测试代码:

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/ioctl.h>
#include <fcntl.h>



main(int argc,char *argv[])
{
    int fd;
    int counter=0;
    int counter_old=0;

    if ((fd=open("/dev/second_drv",O_RDONLY )) < 0)
    {
        printf("Open Device  failed.\r\n");
        exit(1);
    }
    else
        while(1)
            {
                //printf("in the while(1)!\n");
                read(fd,&counter,sizeof(unsigned int));
                if(counter!=counter_old)
                    {
                        printf("seconds after open /dev/second_drv :%d\n",counter);
                        counter_old=counter;
                    }
            }
 
}

 

posted on 2013-09-05 13:43  熊猫酒仙是也  阅读(331)  评论(0编辑  收藏  举报

导航