编写Linux设备驱动程序的注意事项

2023-05-16

编写设备驱动程序的注意事项

应用程序开发与驱动程序开发的差异

在Linux上的程序开发一般分为两种,一种是内核及驱动程序开发,另一种是应用程序开发。这两种开发种类对应Linux的两种状态,分别是内核态和用户态。内核态用来管理用户态的程序,完成用户态请求的工作;用户态处理上层的软件工作。驱动程序与底层的硬件交互,所以工作在内核态。
大多数程序员致力于应用程序的开发,少数程序员则致力于内核及驱动程序的开发。相对于应用程序的开发,内核及驱动程序的开发有很大的不同。最重要的差异包括以下几点:

  • 内核及驱动程序开发时不能访问C库,因为C库是使用内核中的系统调用来实现的,而且是在用户空间实现的。
  • 内核及驱动程序开发时必须使用GNU C,因为Linux操作系统从一开始就使用的是GNU C,虽然也可以使用其他的编译工具,但是需要对以前的代码做大量的修改。
  • 内核支持异步终端、抢占和SMP,,因此内核及驱动程序开发时必须时刻注意同步和并发。
  • 内核只有一个很小的定长堆栈。
  • 内核及驱动程序开发时缺乏像用户空间那样的内存保护机制。
  • 内核及驱动程序开发时浮点数很难使用,应该使用整型数。
  • 内核及驱动程序开发要考虑可移植性,因为对于不同的平台,驱动程序是不兼容的。

GUN C开发驱动程序

GUN C语言最早起源于一个GUN计划,GUN的意思是“GUN is not UNIX”。GUN计划开始于1984年,这个计划的目的是开发一个类似UNIX并且软件自由的完整操作系统。这个计划一直在进行,直到Linus开发Linux操作系统时,GNU计划已经开发出来了很多高质量的自由软件,其中就包括著名的GCC编译器,GCC编译器能够编译GUN C语言。Linus考虑到GUN计划的自由和免费,所以选择了GCC编译器来编写内核代码,之后的很多开发者也使用这个编译器,所以直到现在,驱动开发人员也使用GUN C语言来开发驱动程序。

不能使用C库开发驱动程序

与用户空间的应用程序不同,内核不能调用标准的C函数库,主要的原因在于对于内核来说完整的C库太大了。一个编译的内核大小可以是1MB左右,而一个标准的C语言库大小可能操作5MB。这对于存储容量较小的嵌入式设备来说,是不实用的。缺少标志C语言库,并不是说驱动程序就只能做很好的事情了。
大部分常用的C库函数在内核中都已经实现了。比如操作字符串的函数组就位于内核文件lib/string.c中。只要包含<linux/string.h>,就可以使用它们。又如内存分配的函数也已经包含在include/linux/slab_def.h中实现了。注意:内核程序中包含的头文件是指内核代码树中的内核头文件,不是指开发应用程序时的外部头文件。在内核中实现的库函数中的打印函数printk(),它是C库函数printf()的内核版本。printk()函数和printf()函数有基本相同的用法和功能。

没有内存保护机制

当一个用户应用程序由于编程错误,试图访问一个非法的内存空间,那么操作系统内核会结束这个进程,并返回错误码。应用程序可以在操作系统内核的帮助下恢复过来,而且应用程序并不会对操作系统内核有太大的影响。但是如果操作系统内核访问了一个非法的内存,那么就有可能破坏内核的代码或者数据。这将导致内核处于未知的状态,内核会通过oops错误给用户一些提示,但是这些提示都是不支持、难以分析的。
在内核编程中,不应该访问非法内存,特别是空指针,否则,内核会忽然死掉,没有任何机会给用户提示。对于不好的驱动程序,引起系统崩溃是很常见的事情,所以对于驱动开发人员来说,应该非常重视对内存的正确访问。一个好的建议是,当申请内存后,应该对返回的地址进行检测。

小内核栈

用户空间的程序可以从栈上分配大量的空间存放变量,甚至用栈存放巨大的数据结构或者数组都没问题。之所以能这样做是因为应用程序是非常驻内存的,它们可以动态地申请和释放所有可用的内存空间。内核要求使用固定常驻的内存空间,因此要求尽量少地占用常驻内存,而尽量多地留出内存提供给用户程序使用。因此内核栈的长度是固定大小的,不可动态增长的32位机的内核栈是8KB;64位机的内核栈是16KB。
由于内核栈比较小,所以编写程序时,应该充分考虑小内核栈问题。尽量不要使用递归调用,在应用程序中,递归调用4000多次就有可能溢出,在内核中,递归调用的次数非常少,几乎不能完成程序的功能。另外按使用完内存空间后,应该尽快地释放内存,以防止资源泄漏,引起内核崩溃。

重视可移植性

对于用户空间的应用程序来说,可移植性一直是一个重要的问题。一般可移植性通过两种方式来实现。一种方式是定义一套可移植的API,然后对这套API在这两个需要移植的平台上分别实现。应用程序开发人员,只要使用这套可移植的API,就可以写出可移植的程序。在嵌入式领域,比较常见的API套件是QT。另一种方式是使用类似Java、Actionscript等可移植到很多操作系统上的语言。这些语言一般通过虚拟机执行,所以可以移植到很多平台上。
对于驱动程序来说,可移植性需要注意以下几个问题:

  • 考虑字节顺序,一些设备使用大端字节序,一些设备使用小端字节序。Linux内核提供了大小端字节节序转换的函数。
#define cpu_to_le16(v16) (v16)
#define cpu_to_le32(v32) (v32)
#define cpu_to_le64(v64) (v64)
#define le16_to_cpu(v16) (v16)
#define le32_to_cpu(v32) (v32)
#define le64_to_cpu(v64) (v64)
  • 即使是同一种设备的驱动程序,如果使用的芯片不同,也应该写不同的驱动程序,但是应该给用户提供一个统一的编程接口。
  • 尽量使用宏代替设备端口的物理地址,并且可以使用ifdefine宏确定版本等信息。
  • 针对不同的处理器,应该使用相关处理器的函数。
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

编写Linux设备驱动程序的注意事项 的相关文章

随机推荐

  • H3C交换机SSH配置

    H3C交换机SSH配置 1 使用SSH 43 密码认证 基本SSH配置方法 注 xff1a 在用户使用SSH登录交换机时 xff0c 交换机对所要登录的用户使用密码对其进行身份验证 生成RSA和DSA密钥对 H3C public key l
  • 2022年下半年网络规划设计师考试论文真题

    试题 一 论5G与校园网络融合的规划与设计 近年来 xff0c 教育部等部门印发了 教育信息化2 0行动计划 关于推进教育新型基础设施建 设构建高质量教育支撑体系的指导意见 等文件 xff0c 引导高等学校以信息化为主导 xff0c 面向高
  • 2022年下半年网络规划设计师考试下午真题

    试题一 案例一 某单位网站受到攻击 首页被非法篡改 经安全专业机构调查 该网站有一个两年前被人非法上传的后门程序 本次攻击就是因为其他攻击者发现该后门程序并利用其实施非法篡改 nbsp 案例二 网站管理员某天打开本单位门户网站首页后 发现自
  • 2022年信息安全工程师上午真题及答案解析

    2022年信息安全工程师上午真题及答案解析 1 中华人民共和国网络安全法 第五十八条明确规定 因维护安全和社会公共秩序 处置重大突发社会安全事件的需要 经 nbsp 决定或者批准 可以在特定区域对网络通信采取限制等临时措施 A 国务院 B
  • 2022年信息安全工程师下午真题及答案解析

    2022年信息安全工程师下午真题及答案解析 阅读下列说明 xff0c 回答问题1至问题3 将解答填入答题纸的对应栏内 说明 访问控制是保障信息系统安全的主要策略之一 xff0c 其主要任务是保证系统资源不被非法使用和非常规访问 访问控制规定
  • 华为交换机Console密码重置、设备初始化、默认密码

    1 华为交换机Console密码重置 1 通过Console口连接交换机 xff0c 并重启交换机 2 当界面出现以下打印信息时 xff0c 及时按下快捷键 Ctrl 43 B 并输入BootROM BootLoad密码 xff0c 进入B
  • 华为S7700交换机如何清除console密码

    问题描述 s7700设备如何清除console密码 解决方案 S7703设备清除console密码过程 重新启动设备 xff08 设备单主控启动 xff0c 双主控请拔下一张主控卡 xff09 当设备上电后 xff0c 操作终端屏幕上显示如
  • 华为交换机配置ssh登录远程管理交换机

    配置华为交换机ssh远程登录 xff0c 先配置交换机的管理地址和vlan xff0c 此处为vlan10 xff0c 把接口GE0 0 1划入vlan10 xff0c 管理地址为192 168 10 100 241 创建本地密钥对 配置接
  • Oracle用户被解锁解决方案(1)

    xfeff xfeff 查看被锁的用户 select LOCK DATE username from dba users where username 61 39 USERNAME 39 LOCK DATE为空说明没有锁定 xff0c 非空
  • 华为S5700交换机初始化和配置telnet,ssh用户方法

    华为S5700交换机初始化和配置telnet xff0c ssh用户方法 通过串口线配置S5700 的管理IP地址和网关 xff0c 串口线接在交换机的console口 xff0c ip设置完成后网线接在ETH口 xff1a lt Quid
  • 华为交换机恢复出厂设置

    华为交换机恢复出厂设置 方法一 xff1a 已知用户名和密码场景 lt SW gt reset saved configuration Warning The action will delete the saved configurati
  • 常用网络工具5:网络抓包工具wireshark

    Wireshark xff08 前称Ethereal xff09 是一个网络数据包分析软件 网络数据包分析软件的功能是截取网络数据包 xff0c 并尽可能显示出最为详细的网络数据包数据 Wireshark使用WinPCAP作为接口 xff0
  • OpenHarmony 3.0 虚拟机开发环境

    本文介绍一种简单的OpenHarmony环境搭建方法 首先我们要知道环境搭建包括哪些内容 xff0c 这样我们才好知道如何去搭建 通常来说 xff0c 环境搭建包括这3大部分 xff1a 代码编写 代码编译 代码下载 烧录程序 在OpenH
  • 程序员如何更好的提升自己

    首先你得明白 xff0c 一个人的能力就像一个池塘 xff0c 不断的输入又不断地输出 xff0c 水池的容量以及水的质量决定了输出的高效与否 xff0c 输入大于输出 xff0c 你的池塘就会不断扩大 xff0c 换句话说你会的技能就越来
  • error:D8016 “/ZI”和“/Gy-”命令行选项不兼容 ”问题解决

    VS调试中出现上述问题 进入 项目 gt 属性 gt C C 43 43 xff08 1 xff09 gt 常规 gt 调试信息格式 gt 选择 程序数据库 Zi 或 无 xff08 2 xff09 gt 代码生成 gt 启用函数集链接 g
  • Linux驱动程序开发用户态和内核态 模块机制

    Linux驱动程序开发 用户态和内核态 Linux操作系统分为用户态和内核态 用户态处理上层的软件工作 内核态用来管理用户态的程序 xff0c 完成用户态请求的工作 驱动程序与底层的硬件交互 xff0c 所以工作在内核态 Linux操作系统
  • QT学习第一步 QT下载及安装详细步骤

    下载地址 xff1a QT官方网站 QT下载安装地址 选择的这个 xff1a QT下载安装地址 文件名称选择 xff0c 图中红色箭头详解 xff1a 选择archive QT开发工具安装包文件夹 xff1a 进入之后显示的文件夹 xff1
  • RT-Thread临界段的保护

    临界段的保护 什么是临界段 临界段 xff0c 用一句话概括就是一段在执行时不能被中断的代码段 在RT Thread中 xff0c 临界段最常出现的场景就是对全局变量的操作 xff0c 全局变量就好像是一个靶子 xff0c 谁都可以对其开枪
  • Oracle中expdp与impdp--导入和导出操作步骤

    Oracle expdp 与impdp 一 根据用户导出导入数据 用户和表空间都相同 这些命令必须在Oracle 工具执行 create directory dpdata1 as E oracle home product backup 这
  • 编写Linux设备驱动程序的注意事项

    编写设备驱动程序的注意事项 应用程序开发与驱动程序开发的差异 在Linux上的程序开发一般分为两种 xff0c 一种是内核及驱动程序开发 xff0c 另一种是应用程序开发 这两种开发种类对应Linux的两种状态 xff0c 分别是内核态和用