01. 前言

有多少Linux驱动工程师是通过《Linux设备驱动程序》这本书入门的呢?今天翻到了抽屉里的这本书,想想也是挺感慨的。

Linux设备驱动程序封面

所以重新翻开这本书,通过文章来记录并实践其中的知识要点,加强自己对于Linux驱动的理解。

1. 一些概念

  • 机制:需要提供什么功能
  • 策略:如何使用这些功能
    在编写驱动程序时,应该针对机制编程,而不要强加策略,策略的添加留给上层的应用去添加,这样做的目的是使得驱动程序会更加灵活。

设备分类:

  • 字符设备:能够像字节流(文件)一样被访问的设备,主要实现 openclosereadwrite 等系统调用。文件节点位于 /dev 目录下。
  • 块设备:一次性只能访问一个或者多个完整块,每个块包含512甚至更多的字节。文件节点也位于 /dev 目录下。
  • 网络接口:一个能够和其他主机交换数据的设备,不存在对应的节点,有一套专门的传输函数。

2. 环境搭建

要开发驱动自然需要有Linux系统。我这边选用的是最新的Ubuntu 2020,也可以使用CentOS、DeepIn等操作系统,根据自己的习惯选择就好。

去官网下载ISO镜像文件,安装一个虚拟机或者直接用U盘安装到电脑上都可以,这些应该不需要过多介绍了。还有一些操作过程中的权限问题,也不再具体说明了。

在写驱动代码前我们还需要准备好内核树,什么是内核树呢?

可以理解为内核源码。针对当前的操作系统编写驱动程序,需要与源码中的目标链接,这样编译出来的驱动模块才能够在当前的操作系统中正常运行。

如何准备内核树呢?

其实安装完Ubuntu系统后,其提供了 linux-header,路径为 /usr/src/,如下图所示。

ubuntu系统中的linux-header目录

通过 uname -a 命令查看当前的系统信息,可以看到内核版本号为 5.4.0-40-generic。

uname命令结果

因此,我们基于
/usr/src/linux-headers-5.4.0-40-generic 目录编译模块即可。编译命令如下:

格式:make -C linux-header目录 M=源码目录 modules
示例:make -C /usr/src/linux-headers-5.4.0-40-generic M=/home/que/quehehe modules

前提条件是在源码同目录下的有Makefile文件,内容为:

obj-m += helloworld.o

其中的 helloworld.o 根据编译源文件进行更改。

之前踩的坑

之前根据上面的 uname 命令获取到内核信息后,运行 sudo apt-cache search linux-source 查询可以安装的源码,如下图所示,并安装了其中的5.4.0源码。

查看可以安装的内核源码

基于这个源码进行漫长的编译后,得到的模块不能加载,原因是模块的 vermagic 版本与内核的版本不一致,模块的 vermagic 版本为5.4.44,而不是5.4.0,我也不清楚这是什么原因,所以不采用下载源码并在源码中编译。

3. 源码编译

从上面可知,可以不用自己编译源码了,但上面踩了坑,但还是记录一下上面编译源码过程。

编译源码主要有以下几步:

  • 切换到源码根目录下
  • 运行 make menuconfig 命令,成功后按esc直接退出,得到.config文件
  • 执行make命令,等待编译完成

我在初始编译的过程中出现了以下几个问题,基本都是库缺失,缺什么库下载什么库就好了。

问题1 缺失libncurses-dev

问题1:Unable to find the ncurses package.

解决方法:sudo apt install libncurses-dev

问题2 缺失flex

问题2:flex: not found

解决方法:sudo apt install flex

问题3 缺失bison

问题3:bison: not found

解决方法:sudo apt install bison

问题4 缺失openssl库

问题4:fatal error: openssl/opensslv.h: 没有那个文件或目录

解决方法:sudo apt install libssl-dev

上述的解决方法在Ubuntu 2020中解决了对应问题,如果是其他系统,可能对应库的名字不一样。

解决以上问题后,耐心等待,即可正常编译完成。

©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容