linux驱动开发之helloword

2024-06-04 23:32
文章标签 linux 开发 驱动 helloword

本文主要是介绍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的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/1031437

相关文章

Linux系统中卸载与安装JDK的详细教程

《Linux系统中卸载与安装JDK的详细教程》本文详细介绍了如何在Linux系统中通过Xshell和Xftp工具连接与传输文件,然后进行JDK的安装与卸载,安装步骤包括连接Linux、传输JDK安装包... 目录1、卸载1.1 linux删除自带的JDK1.2 Linux上卸载自己安装的JDK2、安装2.1

Spring Boot + MyBatis Plus 高效开发实战从入门到进阶优化(推荐)

《SpringBoot+MyBatisPlus高效开发实战从入门到进阶优化(推荐)》本文将详细介绍SpringBoot+MyBatisPlus的完整开发流程,并深入剖析分页查询、批量操作、动... 目录Spring Boot + MyBATis Plus 高效开发实战:从入门到进阶优化1. MyBatis

Python基于wxPython和FFmpeg开发一个视频标签工具

《Python基于wxPython和FFmpeg开发一个视频标签工具》在当今数字媒体时代,视频内容的管理和标记变得越来越重要,无论是研究人员需要对实验视频进行时间点标记,还是个人用户希望对家庭视频进行... 目录引言1. 应用概述2. 技术栈分析2.1 核心库和模块2.2 wxpython作为GUI选择的优

Linux卸载自带jdk并安装新jdk版本的图文教程

《Linux卸载自带jdk并安装新jdk版本的图文教程》在Linux系统中,有时需要卸载预装的OpenJDK并安装特定版本的JDK,例如JDK1.8,所以本文给大家详细介绍了Linux卸载自带jdk并... 目录Ⅰ、卸载自带jdkⅡ、安装新版jdkⅠ、卸载自带jdk1、输入命令查看旧jdkrpm -qa

Linux samba共享慢的原因及解决方案

《Linuxsamba共享慢的原因及解决方案》:本文主要介绍Linuxsamba共享慢的原因及解决方案,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教... 目录linux samba共享慢原因及解决问题表现原因解决办法总结Linandroidux samba共享慢原因及解决

新特性抢先看! Ubuntu 25.04 Beta 发布:Linux 6.14 内核

《新特性抢先看!Ubuntu25.04Beta发布:Linux6.14内核》Canonical公司近日发布了Ubuntu25.04Beta版,这一版本被赋予了一个活泼的代号——“Plu... Canonical 昨日(3 月 27 日)放出了 Beta 版 Ubuntu 25.04 系统镜像,代号“Pluc

利用Python开发Markdown表格结构转换为Excel工具

《利用Python开发Markdown表格结构转换为Excel工具》在数据管理和文档编写过程中,我们经常使用Markdown来记录表格数据,但它没有Excel使用方便,所以本文将使用Python编写一... 目录1.完整代码2. 项目概述3. 代码解析3.1 依赖库3.2 GUI 设计3.3 解析 Mark

Linux安装MySQL的教程

《Linux安装MySQL的教程》:本文主要介绍Linux安装MySQL的教程,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教... 目录linux安装mysql1.Mysql官网2.我的存放路径3.解压mysql文件到当前目录4.重命名一下5.创建mysql用户组和用户并修

Linux上设置Ollama服务配置(常用环境变量)

《Linux上设置Ollama服务配置(常用环境变量)》本文主要介绍了Linux上设置Ollama服务配置(常用环境变量),Ollama提供了多种环境变量供配置,如调试模式、模型目录等,下面就来介绍一... 目录在 linux 上设置环境变量配置 OllamPOgxSRJfa手动安装安装特定版本查看日志在

利用Go语言开发文件操作工具轻松处理所有文件

《利用Go语言开发文件操作工具轻松处理所有文件》在后端开发中,文件操作是一个非常常见但又容易出错的场景,本文小编要向大家介绍一个强大的Go语言文件操作工具库,它能帮你轻松处理各种文件操作场景... 目录为什么需要这个工具?核心功能详解1. 文件/目录存javascript在性检查2. 批量创建目录3. 文件