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中SSH服务配置的全面指南

《Linux中SSH服务配置的全面指南》作为网络安全工程师,SSH(SecureShell)服务的安全配置是我们日常工作中不可忽视的重要环节,本文将从基础配置到高级安全加固,全面解析SSH服务的各项参... 目录概述基础配置详解端口与监听设置主机密钥配置认证机制强化禁用密码认证禁止root直接登录实现双因素

在Linux终端中统计非二进制文件行数的实现方法

《在Linux终端中统计非二进制文件行数的实现方法》在Linux系统中,有时需要统计非二进制文件(如CSV、TXT文件)的行数,而不希望手动打开文件进行查看,例如,在处理大型日志文件、数据文件时,了解... 目录在linux终端中统计非二进制文件的行数技术背景实现步骤1. 使用wc命令2. 使用grep命令

SpringBoot开发中十大常见陷阱深度解析与避坑指南

《SpringBoot开发中十大常见陷阱深度解析与避坑指南》在SpringBoot的开发过程中,即使是经验丰富的开发者也难免会遇到各种棘手的问题,本文将针对SpringBoot开发中十大常见的“坑... 目录引言一、配置总出错?是不是同时用了.properties和.yml?二、换个位置配置就失效?搞清楚加

Linux如何快速检查服务器的硬件配置和性能指标

《Linux如何快速检查服务器的硬件配置和性能指标》在运维和开发工作中,我们经常需要快速检查Linux服务器的硬件配置和性能指标,本文将以CentOS为例,介绍如何通过命令行快速获取这些关键信息,... 目录引言一、查询CPU核心数编程(几C?)1. 使用 nproc(最简单)2. 使用 lscpu(详细信

linux重启命令有哪些? 7个实用的Linux系统重启命令汇总

《linux重启命令有哪些?7个实用的Linux系统重启命令汇总》Linux系统提供了多种重启命令,常用的包括shutdown-r、reboot、init6等,不同命令适用于不同场景,本文将详细... 在管理和维护 linux 服务器时,完成系统更新、故障排查或日常维护后,重启系统往往是必不可少的步骤。本文

Python中对FFmpeg封装开发库FFmpy详解

《Python中对FFmpeg封装开发库FFmpy详解》:本文主要介绍Python中对FFmpeg封装开发库FFmpy,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐... 目录一、FFmpy简介与安装1.1 FFmpy概述1.2 安装方法二、FFmpy核心类与方法2.1 FF

基于Python开发Windows屏幕控制工具

《基于Python开发Windows屏幕控制工具》在数字化办公时代,屏幕管理已成为提升工作效率和保护眼睛健康的重要环节,本文将分享一个基于Python和PySide6开发的Windows屏幕控制工具,... 目录概述功能亮点界面展示实现步骤详解1. 环境准备2. 亮度控制模块3. 息屏功能实现4. 息屏时间

基于Linux的ffmpeg python的关键帧抽取

《基于Linux的ffmpegpython的关键帧抽取》本文主要介绍了基于Linux的ffmpegpython的关键帧抽取,实现以按帧或时间间隔抽取关键帧,文中通过示例代码介绍的非常详细,对大家的学... 目录1.FFmpeg的环境配置1) 创建一个虚拟环境envjavascript2) ffmpeg-py

Linux脚本(shell)的使用方式

《Linux脚本(shell)的使用方式》:本文主要介绍Linux脚本(shell)的使用方式,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教... 目录概述语法详解数学运算表达式Shell变量变量分类环境变量Shell内部变量自定义变量:定义、赋值自定义变量:引用、修改、删

Python实例题之pygame开发打飞机游戏实例代码

《Python实例题之pygame开发打飞机游戏实例代码》对于python的学习者,能够写出一个飞机大战的程序代码,是不是感觉到非常的开心,:本文主要介绍Python实例题之pygame开发打飞机... 目录题目pygame-aircraft-game使用 Pygame 开发的打飞机游戏脚本代码解释初始化部