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. mysql基础之数据库备份和恢复的基础知识

    备份数据的最终目的是为了在出现一些意外情况时,能够通过备份将数据还原,所以单单的备份数据往往是无法满足还原时的需求的,所以在备份数据库时,除了要备份数据本身,还要备份相关的数据库环境,如配置文件,定时 ...

  2. 逗号字符的使用、字符数组与字符串数组、sizeof与strlen

    (1)连接两个表达式为一个表达式 for(ux=0,uxt=1;uxt<444;ux++,uxt++) 允许通过编译:他可以给FOR循环更多的初始化值: (2)一般定义的话要区别只有 字符数组 ...

  3. 原型和原型链 prototype和proto的区别

    原型 原型是function对象下的属性,它定义了构造函数的共同祖先,也就是一个父子级的关系,子对象会继承父对象的方法和属性 prototype是函数下的属性,对象想要查看原型使用隐式属性__Prot ...

  4. 第7讲 | ICMP与ping:投石问路的侦察兵

    第7讲 | ICMP与ping:投石问路的侦察兵 ping 是基于 ICMP 协议工作的.ICMP 全称 Internet Control Message Protocol,就是互联网控制报文协议. ...

  5. 处理SpringMVC中遇到的乱码问题

    乱码在日常开发写代码中是非常常见的,以前乱码使用的是通过设置一个过滤器解决, 现在可以使用SpringMVC给提供的过滤器,在web.xml设置,这比我们自己写的过滤器强大的的多. 注意:每次修改了x ...

  6. Oracle数据库使用pfile启动还是spfile启动---oracle

    查看数据库使用pfile启动还是spfile启动 9i版本以后,一般是使用spfile启动,但前提是有这个spfile文件,如果同时存在spfile和pfile文件,会优先选择spfile模式启动数据 ...

  7. OpenCV读写图像文件解析

    OpenCV读写图像文件解析 imdecode 从内存中的缓冲区读取图像. C++:Mat imdecode(InputArray buf, int flags) C++:Mat imdecode(I ...

  8. 基于区域的CNN(R-CNN)

    基于区域的CNN(R-CNN) Region-based CNNs (R-CNNs) 基于区域的卷积神经网络或具有CNN特征的区域(R-CNN)是一种将深度模型应用于目标检测的开创性方法.在本节中,将 ...

  9. python 利用三方的xlrd模块读取excel文件,处理合并单元格

      目的: python能使用xlrd模块实现对Excel数据的读取,且按照想要的输出形式.  总体思路: (1)要想实现对Excel数据的读取,需要用到第三方应用,直接应用. (2)实际操作时候和我 ...

  10. jsp中basa标签的使用

    <base href="http://${pageContext.request.serverName}:${pageContext.request.serverPort}${page ...