linux驱动学习记录

一、背景

在开始学习我的linux驱动之旅之前,先提一下题外话,我是一个c语言应用层开发工作人员,在工作当中往往会和硬件直接进行数据的交互,往往遇到数据不通的情况,常常难以定位,而恰巧驱动是处于应用层和硬件之间的一个重要的数据传输媒介,也是在这个背景下,驱动了我对驱动的好奇心,当抱着了解的心态来的时候,却不知不觉地对驱动的执行方式产生了兴趣,由此也开始了我学习的征途…

二、驱动开发

驱动的作用是用来操作硬件工作,使其应用开发人员能间接实现对功能的开发。驱动函数都是注册在内核当中,应用层代码也都是通过直接调用系统的函数来实现对驱动的数据传递和接收,实现流程如下图所示:

1、驱动环境搭建(内核编译的方式)

  1. 从官网获取,将获取的压缩包解压后放入/usr/src中
  2. 使用apt指令获取
sudo apt-cache search linux-source
sudo apt-get install linux-source-<version>
sudo tar jxvf linux-source-<version>.tar.bz2
  1. 编译源码
 cd /usr/src/linux-source-<version>
#以下三选一
sudo make config #逐一选择kernel的配置形式
#或
sudo make oldconfig #按原有kernel配置配置kernel
#或
sudo make menuconfig #使用可视化环境配置kernel#编译内核的过程
sudo make #编译内核,时间较长,可能会长达1小时及以上,如5.4.0用时约3-5个小时
#此时已完成了镜像编译和所有modules编译,如果不确定可以使用以下指令再编译
sudo make modules #编译内核驱动modules
sudo make bzImage #编译内核镜像#加载modules的过程
sudo make modules_install #安装内核模块
#检查安装
cd /lib/modules
#如果安装正常这里面会出现以版本号为文件名的文件夹,就证明安装成功了,如5.4.xx或5.4.xx-xx-generic

2、驱动加载和卸载的指令

  • lsmod :list moduel 把我们机器上所有的驱动打印出来,
  • insmod:安装驱动
  • rmmod:删除驱动
  • modinfo:打印驱动信息

3、最简单的驱动开始示例

#include <linux/module.h>        // module_init  module_exit
#include <linux/init.h>            // __init   __exit// 模块安装函数
static int __init chrdev_init(void)
{    printk(KERN_INFO "chrdev_init helloworld init\n");return 0;
}// 模块下载函数
static void __exit chrdev_exit(void)
{printk(KERN_INFO "chrdev_exit helloworld exit\n");
}module_init(chrdev_init);
module_exit(chrdev_exit);// MODULE_xxx这种宏作用是用来添加模块描述信息
MODULE_LICENSE("GPL");                // 描述模块的许可证

注:
__init宏告知编译器,将变量或函数放在一个特殊的区域,这个区域定义在vmlinux.lds中。__init将函数放在".init.text"这个代码区中,__initdata将数据放在".init.data"这个数据区中。

标记为初始化的函数,表明该函数供在初始化期间使用。在模块装载之后,模块装载就会将初始化函数扔掉。这样可以将该函数占用的内存释放出来。

__exit宏告知编译器,将函数放在".exit.text"这个区域中。__exitdata宏则告知编译器将数据放在".exit.data"这个区域中。
exit.*区域仅仅对于模块是有用的:如果编译稳定的话,exit函数将永远不会被调用。只有当模块支持无效的时候,exit.*区域将被丢弃。这就是为什么定义中会出现ifdef。

printk是内核的日志函数,日志级别有八个0-7,通过读写/proc/sys/kernel/printk文件可以读取、修改控制台的日志级别,数字越小,级别越高,其实printk始终能输出信息,只不过是在
/var/log/messages文件中,可以通过dmesg来进行查看。

#define KERN_EMERG 0   
#define KERN_ALERT 1   
#define KERN_CRIT 2   
#define KERN_ERR 3   
#define KERN_WARNING 4   
#define KERN_NOTICE 5   
#define KERN_INFO 6   
#define KERN_DEBUG 7

4、驱动编译Makefile的编写

前提: 一定要把源码树目录中主Makefile中ARCH、cross_compile变量的值更改了;

#ubuntu的内核源码树,如果要编译在ubuntu中安装的模块就打开这2个
#KERN_VER = $(shell uname -r)
#KERN_DIR = /lib/modules/$(KERN_VER)/build# 开发板的linux内核的源码树目录
KERN_DIR = /root/driver/kernelobj-m    += module_test.oall:
make -C $(KERN_DIR) M=`pwd` modulescp:
cp *.ko /root/porting_x210/rootfs/rootfs/driver_test.PHONY: clean
clean:
make -C $(KERN_DIR) M=`pwd` modules clean

注:

make -C $(KERN_DIR) M=`PWD` modules

这句话代码的作用就是到 KERN_DIR这个文件夹中 make modules

把当前目录赋值给M,M作为参数传到主目录的Makefile中,实际上是主目录的makefile中有目标modules,下面有一定的规则来编译驱动;

#KERN_VER = $(shell uname -r)#KERN_DIR = /lib/modules/$(KERN_VER)/build

我们在ubuntu中编译内核的时候用这两句代码,因为在ubuntu中为我们保留了一份linux内核的源码树,我们编译的时候直接调用那个源码树的主Makefile以及一些头文件、内核函数等;

了解规则以后,我们设置好KERN_DIR、obj-m这两个变量以后直接make就可以了;

这里注意vermagic 这个的1.8.0-41是你用的linux内核源码树的版本号,只有这个编译的版本号与运行的linux内核版本一致的时候,驱动程序才会被安装

注意license:GPL linux内核开元项目的许可证一般都是GPL这里尽量设置为GPL,否则有些情况下会出现错误;

Linux驱动开发(一)相关推荐

  1. 嵌入式linux驱动开发之点亮led(驱动编程思想之初体验)

    这节我们就开始开始进行实战啦!这里顺便说一下啊,出来做开发的基础很重要啊,基础不好,迟早是要恶补的.个人深刻觉得像这种嵌入式的开发对C语言和微机接口与原理是非常依赖的,必须要有深厚的基础才能hold的 ...

  2. Linux驱动开发环境配置(内核源码树构造)

    来源:季义钦BLOG 作者:季义钦 初次接触Linux驱动程序开发,买了一本<Linux设备驱动程序>,第一件事当然就是构建开发环境了!!! 它上面有一个Hello World的列子: / ...

  3. linux驱动开发的经典书籍

    Linux驱动学习的最大困惑在于书籍的缺乏,市面上最常见的书为<linux_device_driver 3rd Edition>,这是一本很经典的书,无奈Linux的东东还是过于庞大,这本 ...

  4. Linux驱动开发必看详解神秘内核(完全转载)

    Linux驱动开发必看详解神秘内核 完全转载-链接:http://blog.chinaunix.net/uid-21356596-id-1827434.html IT168 技术文档]在开始步入Lin ...

  5. 【嵌入式Linux】嵌入式Linux驱动开发基础知识之Pinctrl子系统和GPIO子系统的使用

    文章目录 前言 1.Pinctrl子系统 1.1.为什么有Pinctrl子系统 1.2.重要的概念 1.3.代码中怎么引用pinctrl 2.GPIO子系统 2.1.为什么有GPIO子系统 2.2.在 ...

  6. 【嵌入式Linux】嵌入式Linux驱动开发基础知识之按键驱动框架

    文章目录 前言 1.APP怎么读取按键值 1.1.查询方式 1.2.休眠-唤醒方式 1.3.poll方式 1.3.异步通知方式 1.5. 驱动程序提供能力,不提供策略 2.按键驱动程序框架--查询方式 ...

  7. 【嵌入式Linux】嵌入式Linux驱动开发基础知识之LED模板驱动程序的改造:设备树

    文章目录 前言 1.驱动的三种编写方法 2.怎么使用设备树写驱动程序 2.1.设备树节点要与platform_driver能匹配 2.2.修改platform_driver的源码 3.实验和调试技巧 ...

  8. 【嵌入式Linux】嵌入式Linux驱动开发基础知识之设备树模型

    文章目录 前言 1.设备树的作用 2.设备树的语法 2.1.设备树的逻辑图和dts文件.dtb文件 2.1.1.1Devicetree格式 1DTS文件的格式 node的格式 properties的格 ...

  9. 【嵌入式Linux】嵌入式Linux驱动开发基础知识之总线设备驱动模型

    文章目录 前言 1.驱动编写的三种方法 1.1.传统写法 1.2.总线驱动模型 1.3.设备树驱动模型 2.Linux实现分离:Bus/Dev/Drv模型 2.1.Bus/Dev/Drv模型 2.2. ...

  10. 【嵌入式Linux】嵌入式Linux驱动开发基础知识之驱动设计的思想:面向对象/分层/分离

    文章目录 前言 1.分离设计 驱动程序分析---程序分层 通用驱动程序---面向对象 个性化驱动程序---分离 APP 程序分析 前言 韦东山嵌入式Linux驱动开发基础知识学习笔记 文章中大多内容来 ...

最新文章

  1. 打印session cookie
  2. 移动Web开发图片自适应两种常见情况解决方案
  3. 017.Zabbix宏介绍
  4. 【音视频架构演进:边缘计算与云原生】
  5. DataList嵌套
  6. java digester_使用digester解析XML配置文件
  7. Chrome谷歌浏览器无需插件设置夜间模式,黑色主题
  8. 各品牌智能电视刷机怎么寻找对应固件包?详细图文教程分享
  9. 机器学习深度神经网络——实验报告
  10. Docker神器之百度云下载(群辉 LEDE)
  11. python可以写什么视觉特效_Python实现视觉特效:一行命令给头像自动戴上口罩的案例...
  12. 牛客网 - 小乐乐打游戏(BFS)
  13. JS 用时间戳计算两个时间之间间隔
  14. 007. RPX服务端和设计端说明
  15. 最全工业以太网通讯协议
  16. 从知识溢出的视角分析开放式协作
  17. 动态规划-最少硬币组合问题(Java)
  18. 07【字符串的扩展】
  19. node.js把前台传来的base64码转成图片存放
  20. 电脑开机为什么老是要两次?

热门文章

  1. android tv盒子哪个好用,2020什么电视盒子最好?超良心的三大实用选购技巧
  2. ASP.NET2.0:利用Localization实现本地化
  3. 5.字符串:aa:zhangsan@163.com!bb:lisi@sina.com!cc:wangwu@126.com 将存入hashMap中 key:aa,bb,cc value:zhang
  4. css中的@mixin的用法
  5. Python爬虫实例(2)--beautifulsoup的应用
  6. VUE3.0——组件传值
  7. 2023 计算机职业规划
  8. Ubuntu服务器上运行mma,一、MMA概述
  9. 项目使用的 safe.cs 帮助类
  10. 阴沟里翻船,我将11月2日定为每年的受耻日!