千家信息网

Linux设备驱动开发的示例分析

发表于:2026-11-01 作者:千家信息网编辑
千家信息网最后更新 2026年11月01日,今天就跟大家聊聊有关Linux设备驱动开发的示例分析,可能很多人都不太了解,为了让大家更加了解,小编给大家总结了以下内容,希望大家根据这篇文章可以有所收获。编译和运行驱动编译要用到kernel的Mak
千家信息网最后更新 2026年11月01日Linux设备驱动开发的示例分析

今天就跟大家聊聊有关Linux设备驱动开发的示例分析,可能很多人都不太了解,为了让大家更加了解,小编给大家总结了以下内容,希望大家根据这篇文章可以有所收获。

编译和运行

驱动编译要用到kernel的Makefile文件 — — 也就是源码树的编译系统。因此,源码需要被配置和编译,以ubuntu自带的源码为例:

编译外部模块(.ko)的编译命令是:

make -CM=mak**e−Cpathtokernelsrc>M=PWD

也就是进入到kernel目录,利用kbuild系统来编译驱动文件。obj-m 告诉编译系统需要编译成一个module(.ko),foo.o表明需要源文件是foo.c或者foo.S,如果驱动模块包含多个文件(如: foo_main.c, foo_common.c),写法如下:

kbuild将编译$(foo-y)列出的所有文件,合并产生 foo.ko

在编译期间,模块的Makefile会被kbuild多次读取,因此建议使用$(KERNELRELEASE)来区分Makefile的使用阶段,优化后的Makefile如下:

第一次运行make的时侯,$(KERNELRELEASE) 为空,因此,Makefile的 ‘else’ 内容首先被读取,然后,执行 *‘make -C …..’*, 执行过程中,会回读Makefile文件,这次, ‘ifneq’ 条件满足,两次走不同的路径,编译系统配置不同的变量参数。

如果,不使用 $(KERNELRELEASE) 区分的话,每次编译系统都会设置所有的变量和规则,可能会与kernel的Makefile变量或者规则冲突,因此,建议在(KERNELRELEASE)为空的情况下,配置driver专用的变量和规则,除了使用(KERNELRELEASE)为空的情况下,配置drive**r专用的变量和规则,除了使用(KERNELRELEASE)外,kernel还提供了一些其它的做法,
更多的kernel 编译系统信息,请参考kernel源码下的 "Documentation/kbuild/"

驱动模块运行相关命令

  • insmod foo.ko —— 加载driver 到kernel去运行。
  • rmmod foo —— 从kernel 移除driver.
  • lsmod —— 查看当前kernel 运行的模块。

字符设备

字符设备驱动实际上就是实现一个文件接口,让设备文件可以像一个普通文件那样来访问,这样应用程序就可以使用libc库的’文件IO API(open/write/read/close 系列函数)‘ 来访问驱动程序,与驱动交换数据,因此,它的核心就是实现文件系统的接口 -- 文件操作。

程序入口

宏内核与微内核的一个最大区别就是驱动程序的运行空间。微内核系统,驱动程序作为一个应用程序,运行在用户空间,它的入口就是应用程序的‘main’函数。 Linux作为一个宏内核系统,它的驱动程序与内核是一体的,运行在内核空间,它的入口是 ‘module_init’,‘module_exit’则是对应的退出函数,它们一定是成对出现的。

foo_init 执行了最基本的字符设备操作:使用 cdev_add 添加一个 ‘cdev’到字符设备列表(其实是一个map结构), 这样就把foo这个字符设备托付给kernel进行管理了,当应用程序操作相应的设备文件时,kernel能调度到foo驱动程序。

foo_exit 一定要使用 cdev_del 从列表里面删除设备,不然,当kernel从列表里面查找到 cdev时,返回的将是"过时"的指针,使用它来 callback相应操作时,就会出现空指针异常,导致kernel会挂掉。切记!foo_init 和 foo_exit 一定要成对使用,执行相反的操作。

bug 实例:

  1. foo_exit 不执行 cdev_del 函数。
  2. insmod foo.ko -- OK。
  3. 应用程序对设备文件读写 -- OK。
  4. rmmod foo -- OK。
  5. insmod foo.ko -- OK。
  6. 应用程序对设备文件读写 -- core dump。

‘rmmod foo’时,会调用 foo_exit,但是,程序员忘了执行 cdev_del 函数,导致 foo.cdev 的指针没有被删除而变成了一个空指针,它仍然在字符设备列表里面。 当第二次插入foo.ko后, 读写该设备时,Kernel找的是旧的 foo.cdev 空指针,用它调用相应的文件操作时,就发生了空指针的 core dump 错误。

文件操作

setup_dev: 注册当前的设备的文件操作函数,当应用程序操作设备文件时,调用到对应的驱动函数。与用户空间交换数据,copy_from/to_user,这两个函数返回0表示函数执行成功。

  • copy_from_user: 把用户写入的数据copy驱动数据buf保存起来。
  • copy_to_user: copy驱动数据buf到 用户读取数据的buf。

应用程序与字符驱动的交互流程

  1. 创建设备文件 -- sudo mknod /dev/foodev c 500 0
  2. 修改设备文件权限 -- sudo chmod 766 /dev/foodev
  3. 应用程序使用open函数打开设备文件。
  4. kernel根据文件类型(字符设备文件)找到字符设备列表,并根据设备号(Major, Minor),找到对应的设备驱动模块。
  5. 调用设备驱动的open函数 foo_open 。
  6. 应用程序调用 read/write函数来读写设备文件。
  7. 驱动调用 foo_read/write并使用copy_from/to_user来交换数据。

常见问题

Q: 读写设备文件时,write或者 read函数返回0,不能读写数据 ?
A: 这类设备文件读写失败问题,很有可能是权限问题,确认下文件读写权限,其次是数据是否符合驱动的要求。

块设备

块设备指的是存储设备,块设备驱动就是存储驱动如:HD,SSD。Linux 用 Block 子系统对它们进行管理,把应用层的IO读写请求,转变为Request ,传给相应的会设备驱动。驱动流程比较简单:

register_blkdev → alloc_disk → 处理request

Q: 文件系统与Block子系统的关系?
A: Block子系统主要是提供最底层的数据读写,也就是raw io,文件系统使用它进行IO操作。

注册

注册块设备(主设备号)

注册设备(MAJOR,MINOR)

添加磁盘

这个磁盘会出现在 /dev 目录下面, 本例是 /dev/frd0,用户可以对设备文件进行格式化,分区等磁盘相关的操作。如: ‘mkfs.ext2 /dev/frd0’, ‘mount /dev/frd0 /mnt’。

初始化请求队列

处理设备请求

kernel 提供了一些宏来帮助遍历请求列表。对请求的处理策略,就是Block驱动最核心最精华的部分,开发者得根据设备的物理特性来提高访问效率,解决并发拥堵等问题。
*fr_queue_rq()* -- ‘**请求队列’**处理函数,在初始化请求队列时设置,Loop处理每个请求:

*fr_transfer()* -- 物理设备读写数据,根据请求的上下文内容(context),进行底层数据传输,这里就是最底层的IO通讯了,驱动根据物理设备的接口协议来进行数据的读写。

块设备驱动测试

执行上面命令后,frd_data_r 和 frd_data_w的内容应该是一样的。

看完上述内容,你们对Linux设备驱动开发的示例分析有进一步的了解吗?如果还想了解更多知识或者相关内容,请关注行业资讯频道,感谢大家的支持。

设备 文件 驱动 程序 函数 编译 数据 系统 应用 应用程序 字符 设备驱动 运行 就是 内容 内核 指针 模块 变量 用户 数据库的安全要保护哪些东西 数据库安全各自的含义是什么 生产安全数据库录入 数据库的安全性及管理 数据库安全策略包含哪些 海淀数据库安全审计系统 建立农村房屋安全信息数据库 易用的数据库客户端支持安全管理 连接数据库失败ssl安全错误 数据库的锁怎样保障安全 互联网佳科技有限公司 中关村互联网科技集团 科技金融是不是互联网金融 互联网是不是新科技 互联网科技卖菜 互联网科技作文 南京欣网互联网科技 居家互联网科技有限公司 互联网科技公司需要的职位 千方科技属于互联网企业吗 知域互联网科技有限公司大骗子 互联网科技商业 长沙互联网科技 上海京穆互联网科技有限公司 江苏互联网智能科技产品出厂价 张家口科技产业互联网平台 互联网科技和医药行业 数字科技和互联网金融哪个好 前海云享互联网科技 武汉亿视互联网科技有限公司 广州大一互联网络科技有限公司 新华互联网科技学院 互联网与未来科技 银优互联网科技有限公司 移动互联网年度科技创新 中国科技创新与世界互联网大会 东莞新华互联网科技学校 济南有互联网科技公司吗 锡山区互联网智能科技产品供应 互联网科技手机排行榜
0