嵌入式培训机构四个月实训课程笔记(完整版)-Linux ARM驱动编程第五天-ARM Linux编程之字符设备驱动(物联技术666)

news2024/11/25 2:58:52

链接:https://pan.baidu.com/s/1V0E9IHSoLbpiWJsncmFgdA?pwd=1688
提取码:1688

教学内容:

1、内核模块的简单框架:

__init __exit执行完后就释放空间

简单框架:包含三个部分

1)模块初始化和模块退出函数

2)注册模块函数

3)模块许可

//***************************************************

#include <linux/module.h>    /*module_init()*/

#include <linux/kernel.h>        /* printk() */

#include <linux/init.h>            /* __init __exit */

static int __init myModule_init(void)   //红色名可自定义,使用static保证只能在本文件中调用

{

       /* Module init code */

       PRINTK("myModule_init\n");

       return 0;

}

static void __exit myModule_exit(void)          //红色名可自定义

{

       /* Module exit code */

       PRINTK("myModule_exit\n");

       return;

}

module_init(myModule_init);    //注册模块函数

module_exit(myModule_exit);   //注册

MODULE_AUTHOR("zhangda");       /*模块作者,可选*/

MODULE_LICENSE("GPL");                   /*模块许可证明,描述内核模块的许可权限,必须*/

MODULE_DESCRIPTION("A simple Hello World Module"); /*模块说明,可选*/

//******************************************

makefile的编写

驱动有两种方式,一为内核树之内,一为内核树以外,前者有点复杂,涉及到将驱动放到合适的内核树目录,修改相应的Makefile以及Kconfig文件,不过,天下无难易之事,为之,难亦不难了;后者所做的劳动就不用那么多了。这个Makfile只适合于后者。此外,内核的Makefile跟一般的应用程序的Makefile不太一样,就像驱动程序跟应用程序,内核头文件跟应用程序头文件等等,没必然关系,或者说是两码事,两者不能混为一谈。再有一点,驱动是跟内核打交道的,你的系统中必须有一个内核源代码。

//*******************************************

obj-m := module_test.o    //目标文件

ifneq ($(KERNELRELEASE),)

KERNELDIR = $(KERNELRELEASE)

else

KERNELDIR = /home/zhangda/linux_kernel/linux-2.6.34    //内核源代码地址

endif

$(PWD) := $(shell pwd)

default:

       $(MAKE) -C $(KERNELDIR) M=$(PWD) modules

       rm -rf *.o *.mod.c *.order *.symvers

clean:

       rm -rf *.ko

//***************************************************

2、模块间符号的相互引用

       在模块编程或内核编程中经常会遇到需要调用其它模块中符号的情况,在内核中专门有一张表来管理这些符号,可以通过 cat/proc/kallsyms查看该内核符号表我们也可以自己编写一个模块,并导出其符号供其它模块使用。

//****************************************

//****************************************

上图1,通过EXPORT_SYMBOL导出模块符号,方便图2使用符号函数。由于是给文件外函数使用,所以不能使用static修饰函数。

3linux字符设备驱动结构

描述字符设备的结构体(详细参考内核和宋宝华的设备驱动书)

//**************************

struct cdev {

       struct kobject kobj;     //内嵌kobject 对象

       struct module *owner;      //所属模块

       const struct file_operations *ops;    //文件操作结构

       struct list_head list;   

       dev_t dev;    //设备号

       unsigned int count;

};

//*****************************

设备号为32位,高12位为主设备号,低20位为次设备号;

此结构体描述了字符设备的信息,其中struct file_operations *ops结构体是向用户提高SPI接口函数的重要结构体。

file_operations :

//*******************************************

#include <linux/fs.h>

struct file_operations {

       struct module *owner;

// 指向拥有该结构的模块的指针,避免正在操作时被卸载,一般为初始化为THIS_MODULES

       loff_t (*llseek) (struct file *, loff_t, int);

       ssize_t (*read) (struct file *, char __user *, size_t, loff_t *);//读接口

       ssize_t (*write) (struct file *, const char __user *, size_t, loff_t *);//写接口

       ssize_t (*aio_read) (struct kiocb *, const struct iovec *, unsigned long, loff_t);

       ssize_t (*aio_write) (struct kiocb *, const struct iovec *, unsigned long, loff_t);

       int (*readdir) (struct file *, void *, filldir_t);

       unsigned int (*poll) (struct file *, struct poll_table_struct *);

       int (*ioctl) (struct inode *, struct file *, unsigned int, unsigned long);//io控制接口

       long (*unlocked_ioctl) (struct file *, unsigned int, unsigned long);

       long (*compat_ioctl) (struct file *, unsigned int, unsigned long);

       int (*mmap) (struct file *, struct vm_area_struct *);

       int (*open) (struct inode *, struct file *);//打开接口

       int (*flush) (struct file *, fl_owner_t id);

       int (*release) (struct inode *, struct file *);//关闭接口

       int (*fsync) (struct file *, struct dentry *, int datasync);

       int (*aio_fsync) (struct kiocb *, int datasync);

       int (*fasync) (int, struct file *, int);

       int (*lock) (struct file *, int, struct file_lock *);

       ssize_t (*sendpage) (struct file *, struct page *, int, size_t, loff_t *, int);

       unsigned long (*get_unmapped_area)(struct file *, unsigned long, unsigned long, unsigned long, unsigned long);

       int (*check_flags)(int);

       int (*flock) (struct file *, int, struct file_lock *);

       ssize_t (*splice_write)(struct pipe_inode_info *, struct file *, loff_t *, size_t, unsigned int);

       ssize_t (*splice_read)(struct file *, loff_t *, struct pipe_inode_info *, size_t, unsigned int);

       int (*setlease)(struct file *, long, struct file_lock **);

};

//****************************************

字符驱动设备的注册:

int register_chrdev(unsigned int major, const char *name,const struct file_operations *fops)

(内联函数)

第一个参数:主设备号,int型,0为内核自动分配

第二个参数:设备名

第三个参数:file_operations的结构体地址

返回分配的主设备号,大于0,错误返回负值。

void unregister_chrdev(MAJOR_NR, DRIVER_NAME);(内联函数)

第一个参数:分配的主设备号

第二个参数:设备名

//*********************

MAJOR_NR = register_chrdev(MAJOR_NR, DRIVER_NAME, &GPG_fops);

if(MAJOR_NR < 0)

{

       PRINTK("register char device fail!\n");

       return MAJOR_NR;

}

unregister_chrdev(MAJOR_NR, DRIVER_NAME);

//*****************************

自动创建节点:

#include<linux/device.h>

static struct class *my_class;

my_class= class_create(THIS_MODULE, "my_class");

device_create(my_class,NULL,dev_n,NULL,"hello");

注意:dev_n = MKDEV(MAJOR_NR, MINOR_NR);

设备卸载删除类和设备节点

device_destroy(my_class,dev_n);

class_destroy(my_class);

//******************************

my_class=class_create(THIS_MODULE,"udev_gpg");

device_create(my_class,NULL, MKDEV(MAJOR_NR, MINOR_NR), NULL,DRIVER_NAME);

device_destroy(my_class,MKDEV(MAJOR_NR, MINOR_NR));

class_destroy(my_class);

//******************************

用户态与内核态数据的交互:

用户应用程序与驱动程序分属于不同的进程空间,因此二者之间的数据应当采用以下函数进行交换

#include <asm/uaccess.h>

copy_to_user(user_buffer, kernel_buffer, n)

//从内核空间拷贝n字节数据到用户空间

copy_from_user(kernel_buffer, user_buffer, n)

//从用户空间拷贝n字节数据到内核空间

put_user(kernel_value, user_buffer)

//从内核空间拷贝一数据变量到用户空间

get_user(kernel_value, user_buffer)

//从用户空间拷贝一数据变量到内核空间

(内核空间数据可是任意类型)

字符设备驱动的流程:

1)、建立__init和__exit函数;并注册这2个函数module_init,module_exit,声明MODULE_LICENSE;

2)、创建file_operations结构体,并指明函数地址;

3)、字符设备驱动的注册,在__init函数里面注册,在__exit注销;

4)、在__init函数里面完成节点创建,在__exit注销节点;

5)、编写file_operations结构体中的函数,具体功能可以结合裸机驱动编写功能

例如:

//***********************************************

#include <linux/module.h>             /*module_init()*/

#include <linux/kernel.h> /* printk() */

#include <linux/init.h>      /* __init __exit */

#include <linux/fs.h>        /* file_operation */

#include <asm/uaccess.h> /* copy_to_user, copy_from_user */      

#include <linux/device.h>  /*class ,class_create ,device_create 等*/

#define GPGCON      (*(volatile unsigned long *)S3C2410_GPGCON) //虚拟地址

#define GPGDAT     (*(volatile unsigned long *)S3C2410_GPGDAT)

#define GPGUP      (*(volatile unsigned long *)S3C2410_GPGUP)

#include "my_ioctl.h"

#define MAJOR_NAME "my_ioctl_drv"

static int MAJOR_NR = 0;

static int MINOR_NR = 0;

struct class *myclass;

static int io_open(struct inode *inode, struct file *filp)

{     }

static int io_release(struct inode *inode, struct file *filp)

{     }

static ssize_t io_read(struct file *filp, char *buf,size_t count, loff_t *f_pos)

{     }

static ssize_t io_write(struct file *filp, const char *buf,size_t count, loff_t *f_pos)

{     }

static int io_ioctl(struct inode *inode, struct file *file,unsigned int cmd, unsigned long arg)

{     }

static struct file_operations ioctl_file_opt = {

       .owner = THIS_MODULE,

       .write = io_write,

       .read = io_read,

       .ioctl = io_ioctl,

       .open = io_open,

       .release = io_release,

};

static int __init my_inctl_init(void)

{

       PRINTK("come in init\n");

       MAJOR_NR = register_chrdev(MAJOR_NR, DRIVER_NAME, &ioctl_file_opt);

       if(MAJOR_NR < 0)

       {

             PRINTK("register char device fail!\n");

             return MAJOR_NR;

       }

       myclass=class_create(THIS_MODULE,"my_ioctl");

       device_create(myclass,NULL, MKDEV(MAJOR_NR, MINOR_NR), NULL,"my_ioctl");

       return 0;

}

static void __exit my_inctl_exit(void)

{

       if(MAJOR_NR > 0)

       {

             unregister_chrdev(MAJOR_NR, DRIVER_NAME);

             device_destroy(myclass,MKDEV(MAJOR_NR, MINOR_NR));

             class_destroy(myclass);

       }

       PRINTK("exit ioctl\n");

       return;

}

module_init(my_inctl_init);

module_exit(my_inctl_exit);

MODULE_LICENSE("GPL");

MODULE_AUTHOR("HB");

//***************************************************

配置s3c2410的文件

cp arch/arm/configs/s3c2410_defconfig .config

make menuconfig(执行s3c2410配置)

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1451725.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

题目:3.神奇的数组(蓝桥OJ 3000)

问题描述&#xff1a; 解题思路&#xff1a; 官方&#xff1a; 我的总结&#xff1a; 利用双指针遍历每个区间并判断是否符合条件&#xff1a;若一个区间符合条件则该区间在其左端点不变的情况下的每一个子区间都符合条件&#xff0c;相反若一个区间内左端点固定情况下有一个以…

排序算法---桶排序

原创不易&#xff0c;转载请注明出处。欢迎点赞收藏~ 桶排序&#xff08;Bucket Sort&#xff09;是一种排序算法&#xff0c;它将待排序的数据分到几个有序的桶中&#xff0c;每个桶再分别进行排序&#xff0c;最后将各个桶中的数据按照顺序依次取出&#xff0c;即可得到有序序…

MySQL免安装版安装教程

官网下载安装包 MySQL :: Download MySQL Community Server (Archived Versions) 选择mysql版本下载 安装配置MySQL 将下载完的Mysql安装包解压到指定目录 打开windos系统的cmd&#xff0c;以管理员身份运行 进入mysql文件夹中的bin目录 安装MySQL的服务mysqld --install 初…

【教程】C++语言基础学习笔记(五)——Vector向量

写在前面&#xff1a; 如果文章对你有帮助&#xff0c;记得点赞关注加收藏一波&#xff0c;利于以后需要的时候复习&#xff0c;多谢支持&#xff01; 【C语言基础学习】系列文章 第一章 《项目与程序结构》 第二章 《数据类型》 第三章 《运算符》 第四章 《流程控制》 第五章…

姿态传感器MPU6050模块之陀螺仪、加速度计、磁力计

MEMS技术 微机电系统&#xff08;MEMS, Micro-Electro-Mechanical System&#xff09;&#xff0c;也叫做微电子机械系统、微系统、微机械等&#xff0c;指尺寸在几毫米乃至更小的高科技装置。微机电系统其内部结构一般在微米甚至纳米量级&#xff0c;是一个独立的智能系统。 微…

C语言指针(初阶)

文章目录 1:内存与地址1.1内存1.2:如何理解编址 2:指针变量与地址2.1:指针变量与解引用操作符2.1.1:指针变量2.1.2:如何拆解指针类型2.1.3:解引用操作符 2.2:指针变量的大小 3:指针变量类型的意义代码1解引用修改前解引用修改后 代码2解引用修改前解引用修改后 4:const修饰指针…

【C语言期末项目-通讯录】-终级版本-可动态申请内存、可存储数据到文件(手把手详细过程,期末评分A+的项目,答辩辅助神博文,建议三连点赞收藏)

目录 ​编辑 前言&#xff1a; 1.项目功能需求分析 2.文件框架说明 3.程序主框架实现 4.创建联系人结构体类型和通讯录结构体类型 4.1创建通讯录 5.程序功能实现--封装功能函数实现不同功能 5.1通讯录初始化 5.2增加联系人 5.3显示所有联系人的信息 5.4删除指定…

BBC英式口语~发音练习~笔记整理

参考资料 原视频地址&#xff1a; https://www.bilibili.com/video/BV1D7411n7bS/?spm_id_from333.1245.0.0&vd_source5986fc7c8e6d754f3ca44233573aeaff 笔记图片

root MUSIC 算法补充说明

root MUSIC 算法补充说明 多项式求根root MUSIC 算法原理如何从 2 M − 2 2M-2 2M−2 个根中确定 K K K 个根从复数域上观察 2 M − 2 2M-2 2M−2 个根的分布 这篇笔记是上一篇关于 root MUSIC 笔记的补充。 多项式求根 要理解 root MUSIC 算法&#xff0c;需要理解多项式求…

DSA 经典数据结构与算法 学习心得和知识总结(三) |有向无环图及其应用

目录结构 注&#xff1a;提前言明 本文借鉴了以下博主、书籍或网站的内容&#xff0c;其列表如下&#xff1a; 1、参考书籍&#xff1a;《算法导论》第三版 就是这本被封神的杰作&#xff0c;就是它&#x1f926; 2、参考书籍&#xff1a;《数据结构》严奶奶版 3、参考书…

Java学习笔记------static

static 创建Javabean类 public class student {private int age;private String name;private String gender;public student() {}public student(int age, String name, String gender) {this.age age;this.name name;this.gender gender;}/*** 获取* return age*/public…

论文解读:Masked Generative Distillation

文章汇总 话题 知识蒸馏 创新点 带掩盖的生成式蒸馏 方法旨在通过学生的遮罩特征来生成老师的特征(通过遮盖学生部分的特征来生成老师的特征)&#xff0c;来帮助学生获得更好的表现 输入:老师:&#xff0c;学生:&#xff0c;输入:&#xff0c;标签:&#xff0c;超参数: 1:使…

CTFshow web(文件上传158-161)

web158 知识点&#xff1a; auto_append_file 是 PHP 配置选项之一&#xff0c;在 PHP 脚本执行结束后自动追加执行指定的文件。 当 auto_append_file 配置被设置为一个文件路径时&#xff0c;PHP 将在执行完脚本文件的所有代码后&#xff0c;自动加载并执行指定的文件。 这…

【springboot+vue项目(十四)】基于Oauth2的SSO单点登录(一)整体流程介绍

场景&#xff1a;现在有一个前后端分离的系统&#xff0c;前端框架使用vue-element-template&#xff0c;后端框架使用springbootspringSecurityJWTRedis&#xff08;登录部分&#xff09;现在需要接入到已经存在的第三方基于oauth2.0的非标准接口统一认证系统。 温馨提示&…

【STM32 CubeMX】I2C查询方式

文章目录 前言一、CubeMX配置IIC二、查询方式的使用2.1 分析一种情况2.2 Master模式2.3 Mem模式 总结 前言 在STM32 CubeMX环境中&#xff0c;I2C&#xff08;Inter-Integrated Circuit&#xff09;通信协议的查询方式是一种简单而常见的通信方式。通过查询方式&#xff0c;微…

代码随想录 Leetcode45. 跳跃游戏 II

题目&#xff1a; 代码(首刷看解析 2024年2月15日&#xff09;&#xff1a; class Solution { public:int jump(vector<int>& nums) {if (nums.size() 1) return 0;int res 0;int curDistance 0;int nextDistance 0;for (int i 0; i < nums.size(); i) {nex…

6、内网安全-横向移动WmiSmbCrackMapExecProxyChainsImpacket

用途&#xff1a;个人学习笔记&#xff0c;有所借鉴&#xff0c;欢迎指正&#xff01; 前言&#xff1a; 在内网环境中&#xff0c;主机192.168.3.31有外网网卡能出网&#xff0c;在取得该主机权限后上线&#xff0c;搭建web应用构造后门下载地址&#xff0c;利用该主机执行相…

Windows系统VMware创建多个CentOS7虚拟机 NAT网络配置 ssh连接

主要目标: 1.创建3个虚拟机, centos7系统 2.虚拟机之间互相访问 3.物理机访问各虚拟机, 通过xshell建立ssh连接 4.物理机网络变化时,仍能访问 用途: NoSQL课程使用, 课前环境搭建,个人备忘 基本信息&#xff1a; 物理机&#xff1a; windows 11 操作系统 虚拟机软件&#xff…

前端工程化面试题 | 10.精选前端工程化高频面试题

&#x1f90d; 前端开发工程师、技术日更博主、已过CET6 &#x1f368; 阿珊和她的猫_CSDN博客专家、23年度博客之星前端领域TOP1 &#x1f560; 牛客高级专题作者、打造专栏《前端面试必备》 、《2024面试高频手撕题》 &#x1f35a; 蓝桥云课签约作者、上架课程《Vue.js 和 E…

OpenCV Mat实例详解 三

OpenCV Mat实例详解 一、二介绍了&#xff0c;OpenCV Mat类构造函数及其公共属性。下面继续介绍OpenCV Mat类公有静态成员函数 OpenCV Mat类公有静态成员函数&#xff08;Static Public Member Functions&#xff09; static CV_NODISCARD_STD Mat diag (const Mat &d)&…