本文主要是介绍linux驱动开发之helloword,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!
自己现在也是刚开始学习linux驱动开发的超级新手 照着别人敲了一个helloworld 然后自己把自己的理解写成注解 如有误请指出,谢谢
#include <linux/module.h>
#include <linux/types.h>#include <linux/fs.h>
#include <linux/errno.h>
#include <linux/mm.h>
#include <linux/sched.h>
#include <linux/init.h>
#include <linux/cdev.h>
#include <asm/io.h>
#include <asm/uaccess.h>
#include <linux/timer.h>
#include <asm/atomic.h>
#include <linux/slab.h>
#include <linux/device.h>
#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驱动开发之helloword的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!