linux驱动开发之helloword

自己现在也是刚开始学习linux驱动开发的超级新手 照着别人敲了一个helloworld 然后自己把自己的理解写成注解 如有误请指出,谢谢


#include

#include
#include
#include
#include
#include
#include
#include
#include
#include
#include    
#include
#include
#include     
           
#define CDEVDEMO_MAJOR 255                       //宏定义主设备号
              
static int cdevdemo_major = CDEVDEMO_MAJOR;   //给设备主设备号赋值


struct cdevdemo_dev   //设备结构体(我目前的理解是,以后比如添加了一个摄像头设备camera,就建立一个camera的结构体)
{   
        struct cdev cdev;
};
    
struct cdevdemo_dev *cdevdemo_devp;        //指向上面那个结构体的结构体指针
    
int cdevdemo_open(struct inode *inode,struct file *filp)       //填写file_operations的open函数
{

        printk(KERN_NOTICE "============ cdevdemo_open");

        return 0;
}


int cdevdemo_release(struct inode *inode,struct file *filp)    //填写file_operations的release函数
{
        printk(KERN_NOTICE "============ cdevdemo_release");
        return 0;
}


static ssize_t cdevdemo_read(struct file *filp,char __user *buf,size_t count,loff_t *ppos)   //填写file_operations的read函数
{
        printk(KERN_NOTICE "============= cdevdemo_read");
}


static const struct file_operations cdevdemo_fops =  //刚刚上面的几个函数分别和file_operations结构体中的函数对应
{
        .owner = THIS_MODULE,
        .open  = cdevdemo_open,
        .release = cdevdemo_release,
        .read = cdevdemo_read,
};


static void cdevdemo_setup_cdev(struct cdevdemo_dev *dev,int index)
{
        printk(KERN_NOTICE "========== cdevdemo_setup_cdev 1");
        int err,devno = MKDEV(cdevdemo_major,index);
        printk(KERN_NOTICE "========== cdevdemo_setup_cdev 2");

        cdev_init(&dev->cdev,&cdevdemo_fops);                                                       //cdev_init主要是

        printk(KERN_NOTICE "========== cdevdemo_setup_cdev 3");
        dev->cdev.owner = THIS_MODULE;
        dev->cdev.ops = &cdevdemo_fops;
        printk(KERN_NOTICE "========= cdevdemo_setip_cdev 4");
        err = cdev_add(&dev->cdev,devno,1);
        printk(KERN_NOTICE "======== cdevdemo_setup_cdev 5");
        if(err)


        {
                printk(KERN_NOTICE "Error %d add cdevdemo %d",err,index);
        }
}


int cdevdemo_init(void)
{
        printk(KERN_NOTICE "==============模块初始化===============");
        int ret;
        dev_t devno = MKDEV(cdevdemo_major,0);     //生成设备号


        struct class *cdevdemo_class;                           //不清楚
        if(cdevdemo_major)                                                        //申请设备号
        {
                printk(KERN_NOTICE "======cdevdemo_init 1");


                ret = register_chrdev_region(devno,1,"cdevdemo");
        }else

       {
                printk(KERN_NOTICE "======= cdevdemo_init 2");
                ret = alloc_chrdev_region(&devno,0,1,"cdevdemo");
                cdevdemo_major = MAJOR(devno);
        }
        if(ret < 0 )                                                                 //申请设备号成功返回0,不成功返回负数,ret<0 说明申请设备号失败
        {
                printk(KERN_NOTICE "设备号申请失败");
                return ret;
        }


        cdevdemo_devp = kmalloc(sizeof(struct cdevdemo_dev),GFP_KERNEL); //分配内存,kmalloc第一个参数是分配大小,第二个详见kmalloc函数
        if(!cdevdemo_devp)                                                                                       //若分配失败 
        {
                ret = -ENOMEM;                                                   
                printk(KERN_NOTICE "Error add cdevdemo");                                   //打印 错误信息
                goto fail_malloc;                                                                                 //跳转到fail_malloc,注销设备号
        }


        memset(cdevdemo_devp,0,sizeof(struct cdevdemo_dev));      //在头文件string.h中定义的 memset 作用主要是为内存初始化一个值
        printk(KERN_NOTICE "========= devdemo_init 3");
        cdevdemo_setup_cdev(cdevdemo_devp, 0);




        cdevdemo_class = class_create(THIS_MODULE,"cdevdemo");
        device_create(cdevdemo_class,NULL, MKDEV(cdevdemo_major,0),NULL,"cdevdemo");


        printk(KERN_NOTICE "======== cdevdemo_init 4");

       return 0;


        fail_malloc:
                unregister_chrdev_region(devno,1);                                                    //注销设备号
}


void cdevdemo_exit(void)                                                                                  //设备remove函数
{
        printk(KERN_NOTICE "End cdevdemo");
        cdev_del(&cdevdemo_devp->cdev);                                                        //调用设备删除函数
        kfree(cdevdemo_devp);                                                                             //释放内存
        unregister_chrdev_region(MKDEV(cdevdemo_major,0),1);                      //主线设备号
}


MODULE_LICENSE("Dual BSD/GPL");
module_param(cdevdemo_major, int, S_IRUGO);    //定模块参数,用于在加载模块时或者模块加载以后传递参数给模块。
module_init(cdevdemo_init);
module_exit(cdevdemo_exit);


你可能感兴趣的:(linux驱动开发)