linux设备驱动是什么,我个人的理解是liunx有用户态和内核态,用户空间中是不能直接对设备的外设进行使用而内核态中却可以,这时我们需要在内核空间中将需要的外设驱动起来供用户空间使用。linux的驱动主要分为字符设备、块设备、和网络设备三类,在分别驱动时需要注意一下,其中驱动不一定单属于哪一类,一个驱动可能属于多种分类。

一、主备材料

可以根据自己的需要准备相应材料,以下是我自己使用的:

开发环境:VMware

操作系统:ubuntu

开发版:湃兔i2S-6UB

二、下载linux内核源码

1.ubuntu内核源码的下载方式,直接通过命令下载即可,下载后源码存放的地址在/usr/src路径下

sudo apt-get install linux-source

经过的测试好像ubuntu不需要下载源码也是可以编写驱动的,具体教程见后面内容。

2.湃兔核的内核源码下载地址:http://i2som-zh.oss-cn-beijing.aliyuncs.com/i2SOM-iMX-Linux-706035a.tar.gz

下载完成后解压到开发环境的路径下,具体路径根据个人爱好。

三、编写驱动

1.入口函数和出口函数

学习编程语言时,代码都会有开始运行的位置,也就是我们所知的入口函数'mian()',同样的原理linux驱动编写也是有入口函数的,只是linux驱动比较特殊,函数基本都是成对存在的,有入口便有出口,所以linux存在入口函数和出口函数,如下所示

module_init(x)  //入口函数
module_exit(x) //出口函数

留意过内核源码的小伙伴都知道,入口和出口函数的定义是在liunx内核源码中的include/linux/init.h文件中,如下图所示:



2.打印函数

linux的驱动中打印日志到控制台的函数和用户空间的打印函数函数名不一样,但是功能和使用方法差不多,linux内核的打印函数是printk()

打印函数的定义是在liunx内核源码中的include/linux/printk.h文件中,如下图所示:



3.编写hello.文件

创建一个hello的驱动文件夹,然后创建hello.c文件,文件内容如下

#include<linux/module.h>
#include<linux/kernel.h>
#include<linux/init.h> static int __init hello_init(void)
{
printk("hello_init\r\n");
return 0;
} static void __exit hello_exit(void)
{
printk("hello_exit\r\n");
} /*
*模块入口与出口函数
*/
module_init(hello_init);
module_exit(hello_exit); MODULE_LICENSE("GPL");
MODULE_AUTHOR("jiaozhu");

4.编写Makefile文件

编写完驱动程序后,需要创建Makefile文件,在这里需要注意x86和arm架构环境下的内容有所不同

x86架构下的Makefile内容如下所示

KERNELDIR := /lib/modules/5.8.0-59-generic/build

CURRENT_PATH := $(shell pwd)
obj-m := hello.o build: kernel_modules kernel_modules:
$(MAKE) -C $(KERNELDIR) M=$(CURRENT_PATH) modules
clean:
$(MAKE) -C $(KERNELDIR) M=$(CURRENT_PATH) clean

注意:ubuntu的所需的内核源码路径在/lib/modules/5.8.0-59-generic/build

arm架构下的Makefile内容如下所示

KERNELDIR := /home/i2SOM-iMX-Linux

CURRENT_PATH := $(shell pwd)
obj-m := hello.o build: kernel_modules kernel_modules:
$(MAKE) -C $(KERNELDIR) M=$(CURRENT_PATH) modules
clean:
$(MAKE) -C $(KERNELDIR) M=$(CURRENT_PATH) clean

注意:编写arm架构的驱动是需要设置交叉编译器,这里没在Makefile文件中设置交叉编译器的原因是我已经在源码的顶层路径Makefile文件中设置了。

5.编译

完成hello.c文件和Makefile文件的编写后,就可以进行编译了,使用make命令进行编译,编译完成完成后会生成.ko文件,如下图所示:



到此驱动的编写已经完成了,细心的小伙伴可能已经注意到我加载和卸载驱动时没有日志输出,具体原因我也不知道,在arm开发板中测试时是有日志输出的。

四、测试

编译完成后生成的hello.ko驱动模块可以通过insmodmodprobe命令加载模块。

1.ubuntu中使用modprobe命令加载模块时需要将.ko文件拷贝到/lib/modules/5.8.0-59-generic路径下,然后在进行加载

sudo cp hello.ko /lib/modules/5.8.0-59-generic -f
sudo depmod
sudo modprobe hello

注意:/lib/modules/5.8.0-59-generic具体的路路径可能不一样,可以进入/lib/modules/目录下查看。

2.arm开发板中使用modprobe命令加载模块时需要将.ko文件拷贝到/lib/modules/路径下,如果路径不存在直接创建相应的路径即可,arm一般测试方式都是通过nfs挂载根文件系统的形式进行测试。

在开发环境中将.ko文件拷贝至rootfs跟文件系统的/lib/modules路径下

sudo cp hello.ko /home/rootfs/lib/modules -f

然后启动开发板,执行加载命令

depmod
modprobe hello

3.查看加载的驱动和卸载驱动

在任意路径下使用lsmod命令即可查看驱动模块,如下图所示:



完成后可以通过rmmod hello卸载驱动模块,注意在ubuntu下可能需要通过root权限才能卸载。

到此我们简单的驱动模块已经编写完成,有写得不好的地方忘各位大佬支出。

参考文献

【驱动】linux设备驱动·入门:https://www.cnblogs.com/lcw/p/3159386.html

正点原子视屏教程:https://www.bilibili.com/video/BV1fJ411i7PB?p=3

linux设备驱动编写入门的更多相关文章

  1. linux设备驱动编写_tasklet机制

    在编写设备驱动时, tasklet 机制是一种比较常见的机制,通常用于减少中断处理的时间,将本应该是在中断服务程序中完成的任务转化成软中断完成. 为了最大程度的避免中断处理时间过长而导致中断丢失,有时 ...

  2. linux设备驱动编写_tasklet机制(转)

    在编写设备驱动时, tasklet 机制是一种比较常见的机制,通常用于减少中断处理的时间,将本应该是在中断服务程序中完成的任务转化成软中断完成. 为了最大程度的避免中断处理时间过长而导致中断丢失,有时 ...

  3. [ARM-LInux开发]linux设备驱动makefile入门解析

    以下内容仅作参考,能力有限,如有错误还请纠正.对于一个普通的linux设备驱动模块,以下是一个经典的makefile代码,使用下面这个makefile可以完成大部分驱动的编译,使用时只需要修改一下要编 ...

  4. 【驱动】linux设备驱动·入门

    linux设备驱动 驱动程序英文全称Device Driver,也称作设备驱动程序.驱动程序是用于计算机和外部设备通信的特殊程序,相当于软件和硬件的接口,通常只有操作系统能使用驱动程序. 在现代计算机 ...

  5. 【驱动】linux设备驱动·字符设备驱动开发

    Preface 前面对linux设备驱动的相应知识点进行了总结,现在进入实践阶段! <linux设备驱动入门篇>:http://infohacker.blog.51cto.com/6751 ...

  6. 浅谈Android系统移植、Linux设备驱动

    一.Android系统架构 第一层:Linux内核 包括驱动程序,管理内存.进程.电源等资源的程序 第二层:C/C++代码库 包括Linux的.so文件以及嵌入到APK程序中的NDK代码 第三层:An ...

  7. linux设备驱动概述,王明学learn

    linux设备驱动学习-1 本章节主要学习有操作系统的设备驱动和无操作系统设备驱动的区别,以及对操作系统和设备驱动关系的认识. 一.设备驱动的作用 对设备驱动最通俗的解释就是“驱使硬件设备行动” .设 ...

  8. linux设备驱动归纳总结(十三):1.触摸屏与ADC时钟【转】

    本文转载自:http://blog.chinaunix.net/uid-25014876-id-119723.html linux设备驱动归纳总结(十三):1.触摸屏与ADC时钟 xxxxxxxxxx ...

  9. linux设备驱动归纳总结(十二):简单的数码相框【转】

    本文转载自:http://blog.chinaunix.net/uid-25014876-id-116926.html linux设备驱动归纳总结(十二):简单的数码相框 xxxxxxxxxxxxxx ...

随机推荐

  1. crontab简单使用手册

    Linux定时任务(1)- crontab 枫林风雨关注 0.1682018.12.14 12:29:47字数 946阅读 921 执行定时任务 crontab 执行循环任务 at 执行一次性任务 c ...

  2. Linux 部署 iSCSI 服务端

    Linux 部署 iSCSI 服务端 服务端实验环境 iSCSI-server :RHEL8 IP:192.168.121.10 一.服务端安装 target 服务和 targetcli 命令行工具 ...

  3. nginx负载均衡搭建phpmyadmin加入redis了解session会话原理

    myphpadmin项目理解cookie和session 当我们平时上网的时候,在刷新之后或者退出浏览器再次打开浏览器不需要登陆网页了,这就是利用了cookie和session: 环境配置 hostn ...

  4. hugboy源库

    =[个人整理的一些源库,均来自网络]= -[Ubuntu]- #阿里源 Ubuntu 20.04 deb http://mirrors.aliyun.com/ubuntu/ focal main re ...

  5. jmeter while控制器踩坑

    在使用jmeter测试一个复杂流程,需要用到while控制器,对于里面的contition,使用jexl3方式,怎么看都没有问题,可是死活跳不出流程,各种莫名其妙的报错,甚至用单个写死的变量(已设置为 ...

  6. Scala 函数式编程思想

    Spark 选择 Scala 作为开发语言 在 Spark 诞生之初,就有人诟病为什么 AMP 实验室选了一个如此小众的语言 - Scala,很多人还将原因归结为学院派的高冷,但后来事实证明,选择 S ...

  7. Apple macOS 下载汇总

    macOS Big Sur 11,macOS Catalina 10.15,macOS Mojave 10.14,macOS High Sierra 10.13,macOS Sierra 10.12 ...

  8. Python+Selenium学习笔记2 - 字符串

    跟着网络课程学了几个小程序. 1.判断a字符串是否为b字符串的子串 1 # coding = utf-8 2 3 # 判断str_a字符串是否为str_b字符串的子串 4 5 str_a = &quo ...

  9. 五、SVM推导过程

    SVM 时间复杂度一般为O(N³) 最重要的是推导过程 NIPS(机器学习顶级会议) 如果给定一个训练集,我们的目标是给定一个边界(一条线),离他最近的训练集样本路越宽越好 下面的几张图反映了SVM的 ...

  10. NVIDIA 自动驾驶软件平台

    NVIDIA 自动驾驶软件平台 Software Developers using DRIVE AGX Developer Kits may choose between: DRIVE OS 5.2. ...