实现内核驱动程序模块

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了实现内核驱动程序模块相关的知识,希望对你有一定的参考价值。

例子是从《android系统源代码情景分析》第二章抄过来的,在学习的过程中还是遇到了不少的问题。

个人体会:在学习第二章之前应该把《Linux设备驱动程序》这本书至少前四章要读一遍,理解一些基础概念和背景知识,不过这本书还是略旧,比如sysfs就没有解释,多google吧。

本书第二章要理解透了再往下进行,因为这个简单的例子从下往上贯穿了Android系统各层,是理解后面各章的基础。

下面列出我遇到的问题和解决办法。

  • 三类文件系统接口的关系、作用分别是什么?

它实现了proc文件系统接口、传统的设备文件系统接口和devfs文件系统接口。

类Unix系统有一条基本的设计哲学:几乎所有的数据实体都被抽象成统一的接口——文件来看待。procfs、devfs和sysfs都是这种设计的体现。

/dev目录下每一个文件对应一个设备,通过操作这些文件可以实现与内核的交互,但devfs存在一些缺点,如命名不灵活,不能任意指定文件名,而且所有文件都在/dev/根目录下。进而演生出sysfs,它把实际连接到系统上的设备组织成一个分级的文件体系,比devfs更清晰更便于管理,sysfs挂载在/sys下面。

/proc文件系统中主要包含三大类内容:进程相关部分、系统信息部分和系统自信息部分。显然在本例中,procfs和sysfs部分的接口,作为入门第一个样例来说并不必要。

因此我打算只实现传统设备文件系统接口的部分,sysfs和procfs暂不实现。我认为依然可以完整地正常工作。

  • 编译问题

  • 在__freg_setup_dev函数中,对函数init_MUTEX的调用编译出错,这是因为该函数已经被启用,改成如下即可:

sema_init(&(dev->sem), 1);
  • 修改内核Kconfig文件。我编译的内核是3.4,需要在drivers/Kconfig中添加
source "drivers/freg/Kconfig"

而不是在arch/arm/Kconfig中。


 

  • 配置

  • 在Mac OSX,调用make menuconfig的时候出错,解决办法已经更新到《Android源码、内核编译》这篇博文里了。
  • 进入make menuconfig配置界面后,如果要设置Enable loadable module support,这块的交互有点坑爹。初次进入界面是这样的,Enable loadable module support没有被选中:

技术分享

如果直接回车进入子菜单,发现前面是---,是不能被修改的:

技术分享

我以为是自己的内核版本有问题,倒腾了半天才明白:应该在一级界面中先对Enable loadable module support按下Y,使之选中:

技术分享

然后再回车进入才能看到并修改子项内容:

技术分享

一万头草泥马崩腾而过,害老子研究半天……


 

  • 调试

  • 查看内核log

我把模块编译到内核中,起初却在/dev下面找不到freg文件,必须要调试代码看在哪一步出了错。freg.c源码多出调用printk函数写了日志,我在每条日志字串头部加了[freg]的字样,如下:

printk(KERN_ALERT"[freg]Initializing freg device.\\n");

以便在浩瀚的内核日志中筛选出freg的日志。

  • 方法一:可以使用dmesg查看内核打印信息,再配合grep如下:

$ adb shell
$ dmesg | grep "\\[freg\\]"
[freg]Initializing freg device.
[freg]Succeeded to initialize freg device.
  •  方法二:可以在运行emulator的时候加-show-kernel参数:
$ emulator -kernel arch/arm/boot/zImage -show-kernel &

 

以上是关于实现内核驱动程序模块的主要内容,如果未能解决你的问题,请参考以下文章

如何使用模块化代码片段中的LeakCanary检测内存泄漏?

嵌入式Linux驱动开发 02:将驱动程序添加到内核中

[Mini2440] 最简单的内核模块

Linux驱动模块编译进内核中

什么是在 C++ 中获取总内核数量的跨平台代码片段? [复制]

静态插入linux内核模块