Linux设备驱动开发详解讲座
《Linux设备驱动开发》PDF课件

PDF 文件使用 "pdfFactory Pro" 试用版本创建
释 放
资可得 源获 内空 核间
华清远见
v 两个半部
中断
v 机制
Ø
tasklet 工作队列
1 /*定义tasklet和底半部函数并关联*/ 2 void xxx_do_tasklet(unsigned long); 3 DECLARE_TASKLET(xxx_tasklet, xxx_do_tasklet, 0);4 5 /*中断处理底半部*/ 6 void xxx_do_tasklet(unsigned long) 7 {... 9 } 11 /*中断处理顶半部*/ 12 irqreturn_t xxx_interrupt(int irq, void *dev_id, struct pt_regs *regs) 13 { 15 16 ...} ... tasklet_schedule(&xxx_tasklet);
驱中 立 设的 口 动 独于 备 接 硬 件 驱 中硬 操 动 的 件作 串 口 LD E FA LS H 硬 件
non-os驱动与应用
on-os驱动与应用
PDF 文件使用 "pdfFactory Pro" 试用版本创建
华清远见
并发和竞态
l 并发和竞态:
Ø 对称多处理器 (SMP)的多个CPU Ø 单CPU内进程与抢占它的进程 Ø 中断(硬中断、软中断、Tasklet、底半部)与进程之间
v v
v v
v
PDF 文件使用 "pdfFactory Pro" 试用版本创建
华清远见
Linux设备驱动的现状
v 高驱动的需求
Linux下PCI设备驱动开发详解

一、设备驱动程序概述自Linux在中国发展以来,得到了许多公司的青睐。
在国内的玩家也越来越多了,但目前还是停留在玩的水平上,很少有玩家对Linux的系统进行研究。
因为它的开放,我们可以随时拿来“把玩”。
这也是Linux一个无可比拟的优势,这样我们可以修改后再加入到里面。
但很少有专门的书籍讲到Linux驱动程序的开发,像上海这样的大城市也很少有讲Linux驱动开发的资料,唉,谁让这个是人家的东西呢,我们还是得跟着人家跑。
我现在讲的这些驱动开发的细节,并不特定哪个版本的内核,这只是大体的思路与步骤。
因为大家都知道Linux 2.6.x 与Linux 2.4.x是有不少改动的。
所以,具体的大家可以去参考Linux Device Driver 2.4 和Linux Device Driver 2.6这几本书。
这是我们学习开发驱动必不可少的东西。
好了,下面就开始学习吧。
根据设备的行为,我们可以把设备分为字符设备和块设备,还有网络设备。
字符设备是以字节为单位进行顺序读写,数据缓冲系统对它们的访问不提供缓存。
而块设备则是允许随机访问与读写,每次读写的数据量都是数据块长度的整数倍,并且访问还会经过缓冲区缓存系统才能实现。
与Unix版本不同的是:Linux的内核允许不是数据块长度整数倍的数据量被读取,用官方的语言就是:但这种不同只是纯粹学术方面的东西。
大多数设备驱动程序都要通过文件系统来进行访问的,但网络设备是不同的。
/dev子目录里都是关于设备的特殊文件,但看起来它们与普通的目录没有什么两样。
如下:$ ls -l /dev...brw-rw--- 1 root disk 22, 1 May 5 1998 hdc1crw-rw--- 1 root daemon 6 0 May 5 1998 lp0与普通文件有所不同是开头的“C” 和“B”,即char 和block的意思,即字符设备和块设备。
再后面的“22,1” 和“6,0”即设备的主设备号和次设备号,主设备号表明它是哪一种设备,这与你在Windows里添加硬件时看到的那些是一个意思。
linux设备驱动(27)usb驱动-热插拔详解

linux设备驱动(27)usb驱动-热插拔详解1 热插拔的基本概念1.1 usb热插拔的硬件原理在USB集线器(hub)的每个下游端⼝的D+和D-上,分别接了⼀个15K欧姆的下拉电阻到地。
这样,在集线器的端⼝悬空时,就被这两个下拉电阻拉到了低电平。
⽽在USB设备端,在D+或者D-上接了1.5K欧姆上拉电阻。
对于全速和⾼速设备,上拉电阻是接在D+上;⽽低速设备则是上拉电阻接在D-上。
这样,当设备插⼊到集线器时,由1.5K的上拉电阻和15K的下拉电阻分压,结果就将差分数据线中的⼀条拉⾼了。
集线器检测到这个状态后,它就报告给USB主控制器(或者通过它上⼀层的集线器报告给USB主控制器),这样就检测到设备的插⼊了。
USB⾼速设备先是被识别为全速设备,然后通过HOST和DEVICE两者之间的确认,再切换到⾼速模式的。
在⾼速模式下,是电流传输模式,这时将D+上的上拉电阻断开。
1.2 热插拔的概念热插拔(hot-plugging或Hot Swap)即带电插拔,热插拔功能就是允许⽤户在不关闭系统,不切断电源的情况下取出和更换损坏的硬盘、电源或板卡等部件,从⽽提⾼了系统对灾难的及时恢复能⼒、扩展性和灵活性等,例如⼀些⾯向⾼端应⽤的磁盘镜像系统都可以提供磁盘的热插拔功能。
具体⽤学术的说法就是:热替换(Hot replacement)、热添加(hot expansion)和热升级(hot upgrade)1.3 热插拔的优点在系统开机情况下将损坏的模块移除,还可以在开机情况下做更新或扩容⽽不影响系统操作。
由于热插拔零件的可靠度提升,还可以将它们⽤做断电器,⽽且因为热插拔能够⾃动恢复,有很多热插拔芯⽚为系统提供线路供电情况的信号,以便系统做故障分析,因此减少了成本。
2 热插拔的实现2.1 Linux下USB HUB的驱动的实现和分析:在系统初始化的时候在usb_init函数中调⽤usb_hub_init函数,就进⼊了hub的初始化。
LINUX设备驱动开发详解

LINUX设备驱动开发详解概述LINUX设备驱动开发是一项非常重要的任务,它使得硬件设备能够与操作系统进行有效地交互。
本文将详细介绍LINUX设备驱动开发的基本概念、流程和常用工具,帮助读者了解设备驱动开发的要点和技巧。
设备驱动的基本概念设备驱动是连接硬件设备和操作系统的桥梁,它负责处理硬件设备的输入和输出,并提供相应的接口供操作系统调用。
设备驱动一般由设备驱动程序和设备配置信息组成。
设备驱动程序是编写解决设备驱动的代码,它负责完成设备初始化、IO操作、中断处理、设备状态管理等任务。
设备驱动程序一般由C语言编写,使用Linux内核提供的API函数进行开发。
设备配置信息是定义硬件设备的相关参数和寄存器配置的文件,它告诉操作系统如何与硬件设备进行交互。
设备配置信息一般以设备树或者直接编码在设备驱动程序中。
设备驱动的开发流程设备驱动的开发流程包括设备初始化、设备注册、设备操作函数编写和设备驱动注册等几个主要步骤。
下面将详细介绍这些步骤。
设备初始化设备初始化是设备驱动开发的第一步,它包括硬件初始化和内存分配两个主要任务。
硬件初始化是对硬件设备进行基本的初始化工作,包括寄存器配置、中断初始化等。
通过操作设备的寄存器,将设备设置为所需的状态。
内存分配是为设备驱动程序分配内存空间以便于执行。
在设备初始化阶段,通常需要为设备驱动程序分配一块连续的物理内存空间。
设备注册设备注册是将设备驱动程序与设备对象进行关联的过程,它使得操作系统能够正确地管理设备。
设备注册包括设备号分配、设备文件创建等操作。
设备号是设备在系统中的唯一标识符,通过设备号可以找到设备对象对应的设备驱动程序。
设备号分配通常由操作系统负责,设备驱动程序通过注册函数来获取设备号。
设备文件是用户通过应用程序访问设备的接口,它是操作系统中的一个特殊文件。
设备文件的创建需要通过设备号和驱动程序的注册函数来完成。
设备操作函数编写设备操作函数是设备驱动程序的核心部分,它包括设备打开、设备关闭、读和写等操作。
Linux设备驱动程序课件(PPT 62页)

驱动程序中的内存分配
在Linux内核模式下,不能使用用户态的malloc() 和free()函数申请和释放内存。
内核编程最常用的内存申请和释放函数为 kmalloc()和kfree(),其原型为:
Linux设备驱动
广州嵌入式软件公共技术支持中心 梁老师
2007年07月
设备驱动概述
操作系统是通过各种驱动程序来驾驭硬件设备,它为 用户屏蔽了各种各样的设备,硬件设备的抽象。
设备驱动程序:处理和管理硬件控制器的软件。 设备驱动程序是操作系统内核和机器硬件之间的接口。
设备驱动概述
设备由两部分组成,一个是被称为控制器的电器部分, 另一个是机械部分。
设备驱动概述
Linux操作系统把设备纳入文件系统的范畴来管理。 文件操作是对设备操作的组织和抽象。设备操作则是
对文件操作的最终实现。 每个设备都对应一个文件名,在内核中也就对应一个
索引节点。 对文件操作的系统调用大都适用于设备文件。 从应用程序的角度看,设备文件逻辑上的空间是一个
一些重要的数据结构
文件操作结构体file_operations
结构体file_operations在头文件 linux/fs.h中定义, 用来存储驱动内核模块提供的对设备进行各种操作 的函数的指针。
结构体的每个域都对应着驱动模块用来处理某个被 请求的事务的函数的地址。
struct file_operations { struct module *owner; loff_t(*llseek) (struct file *, loff_t, int); ssize_t(*read) (struct file *, char __user *, size_t, loff_t *); ssize_t(*write) (struct file *, const char __user *, size_t, loff_t *); 。。。
chapter14 驱动开发基础与调试34页PPT

【学习目标】 •介绍了字符设备的基础知识 •介绍了常见的字符设备驱动开发结构 •介绍了字符设备的驱动开发方法 •介绍了简单的驱动开发调试知识
Page 1
机械工业出版社
2020/1/10
第14章linux驱动开发基础与调试
14 .1
设备驱动简介
14.2
设备驱动基础
Page 6
机械工业出版社
2020/1/10
各个模块被分别编译并链接成一组目标文件,这些文件能被载入 正在运行的内核,或从正在运行的内核中卸载。必要时内核能请 求内核守护进程Kerneld对模块进行加载或卸载。根据需要动态 载入模块可以保证内核达到最小,并且具有很大的灵活性。内核 模块一部分保存在Kernel中,另一部分在Modules包中。在项目 一开始,很多地方对设备安装、使用和改动都是通过编译进内核 来实现的,对驱动程序稍微做点改动,就要重新烧写一遍内核, 而且烧写内核经常容易出错,还占用资源。模块采用的则是另一 种途径,内核提供一个插槽,它就像一个插件,在需要时,插入 内核中使用,不需要时从内核中拔出。这一切都由一个称为 Kerneld的守护进程自动处理。
除了上面对设备的分类的方式之外,还有许多比较特殊的设备,如IIC 、USB、RTC和PCI等,只不过在实际中大部分设备驱动的开发都属于 这三种类型,所以通常说的Linux设备驱动程序开发一般指这三类设备 驱动的开发。
Page 5
机械工业出版社
2020/1/10
内核空间和用户空间
在Linux操作系统中,一般称执行态为“内核空间”和“用户空间”, 在Linux系统中,内核在最高级执行,也称为“管理员态”,也就是我 们常说的“root”用户登录,在这一级任何操作都可以执行。而应用程 序则执行在最低级,所谓的“用户态”,在这一级处理器禁止对硬件的 直接访问和对内存的未授权访问。模块是在所谓的“内核空间”中运行 的,而应用程序则是在“用户空间”中运行的。它们分别引用不同的内 存映射,也就是程序代码使用不同的“地址空间”。
Linux设备驱动开发入门-Read
Linux设备驱动开发入门本文以快捷而简单的方式讲解如何像一个内核开发者那样开发linux设备驱动源作者: Xavier Calbet版权:GNU Free Documentation License 翻译: 顾宏军()中文版权:创作共用.署名-非商业用途-保持一致知识准备要开发Linux 设备驱动,需要掌握以下知识:•C 编程 需要掌握深入一些的C 语言知识,比如,指针的使用,位处理函数,等。
•微处理器编程 需要理解微机的内部工作原理:存贮器地址,中断,等。
这些内容对一个汇编程序员应该比较熟悉。
Linux 下有好几种不同的设备。
为简单起见,本文只涉及以模块形式加载的字符设备。
使用2.6.x 的内核。
(特别是Debian Sarge 使用的2.6.8内核。
)用户空间和内核空间当你开发设备驱动时,需要理解“用户空间”和内核空间之间的区别。
1:2:3:4:5:6:7:8:9:10:11:12:13:14:15:16:17:18:19:20:21:22:23:24:25:•内核空间 :Linux 操作系统,特别是它的内核,用一种简单而有效的方法管理机器的硬件,给用户提供一个简捷而统一的编程接口。
同样的,内核,特别是它的设备驱动程序,是连接最终用户/程序员和硬件的一坐桥或者说是接口。
任何子程序或者函数只要是内核的一部分(例如:模块,和设备驱动),那它也就是内核空间的一部分。
•用户空间. 最终用户的应用程序,像UNIX 的shell 或者其它的GUI 的程序(例如,gedit),都是用户空间的一部分。
很显然,这些应用程序需要和系统的硬件进行交互。
但是,他们不是直接进行,而是通过内核支持的函数进行。
它们的关系可以通过下图表示:图1: 应用程序驻留在用户空间, 模块和设备驱动驻留在内核空间26:27:28:29:30:31:32:33:34:35:36:37:38:39:40:用户空间和内核空间之间的接口函数内核在用户空间提供了很多子程序或者函数,它们允许用户应用程序员和硬件进行交互。
浅谈嵌入式Linux系统设备驱动的开发与设计
&I rv Od i
irt fe) ( { r t( E N_ E T“O r e gs ralr!) } pi kK R AL R I di r e ie i e” n v r t fu
设 备 驱 动 程 序 在 Ln x内核 中 占 有 极 其 重 要 的 位 置 , iu 它是 内核用 于完 成对 物理 设 备 的控制 操作 的 功能 模块 。
对设备 的请求 能满足用 户的要求 。 就返 回请求 的数据 ; 否
则。 就调用请 求 函数 来进行 实际 的 I 操作 。网络设 备可 / O 以通 过 B D套接 口访问数据 。所 有嵌入式 Ln x设备驱 S iu 动程 序都有一 些共性 ,是编写 所有类 型 的驱动程 序都通 用 的 , 作系统提供 给驱动 程序 的支持也大致 相 同。 操 这些
I fr a in T c n l g ・ 息技 术 ・ 硬件 n om to e h oo y 信 软
浅谈 嵌 入 式 Ln x系统 设 备 驱 动 的 iu 开发 与设 计
张 玲 玲
( 大庆油 田有 限责任公 司第十采油厂信 息 中心 黑龙 江大庆 16 0 ) 64 5
【 摘
要 】 主要 阐述 了嵌 入式 L u 设备 驱动程 序的概念 , ix n 归纳 嵌入式 L u 设备驱 动程序 的共 性 。 ix n 探讨嵌 入式 L u ix n
【 ew r e bde s m lu;ei i r e e Ky od m edd yt ;nxdv dv ; r l s】 se i e c re, n k
原子嵌入式linux驱动开发详解
原子嵌入式linux驱动开发详解原子嵌入式Linux驱动开发详解:Linux操作系统一直都是工业控制、物联网、安防等领域中嵌入式设备的首选操作系统。
Linux系统的优良特性使其成为用户和开发者的首选,而Linux内核驱动则是面向嵌入式应用领域核心技术之一。
它是嵌入式设备在硬件及软件之间接口的重要组成部分。
本文将详细介绍使用原子嵌入式Linux驱动进行嵌入式设备驱动的开发,并且介绍使用原子嵌入式Linux驱动实现并行的多线程驱动。
一、嵌入式设备驱动的基本原理:所谓嵌入式设备驱动,就是处理器与外部设备之间进行数据传递的程序,将设备中的信息读取到处理器中,或将处理器中的信息发送至设备中。
嵌入式设备驱动的核心逻辑是控制输入输出模块,以完成外部信息的读取和发送任务。
在Linux系统下,设备驱动一般以内核模块存在,片上驱动是一个相对独立的模块,不妨做一番详细的介绍。
二、原子嵌入式Linux驱动的使用:原子嵌入式Linux驱动根据功能的不同划分成了两类,即原子操作和读写自旋锁。
这两类驱动的使用方法不同,且有自己的特殊应用场景。
1、原子操作:在多线程的情况下,通过锁来保证同一时间只能有一个线程操作共享资源是一种常见的方法。
原子操作则是一种替代锁的方式,在多线程操作共享资源的情况下采用原子操作方式相对于锁来说会更加高效。
原子操作是一种特殊的指令操作,执行完原子操作之后,CPU不允许其他线程读写该地址的值,因此可以避免竞争。
下面是一个使用原子操作的例子:radio_chan = atomic_read(&radio->chan);digital_chan =atomic_read(&radio->digital_chan);radio_write_register(radio, 0x0011, 2,&radio_chan);radio_write_register(radio, 0x5111, 2,&digital_chan);在上述代码中,使用了atomic_read来获得变量radio_chan和digital_chan的值,这两个变量是共享资源,这里使用原子操作来避免竞争和冲突。
Linux设备驱动开发详解第二版 宋宝华
1.4.2linux设备驱动与整个软硬件系统的关系
1.4.3linux设备驱动的重点、难点
1.5linux设备驱动开发环境构建
1.5.1pc上的linux环境
1.5.2ldd6410开发板
1.5.3工具链安装
1.5.4主机端nfs和trip服务安装
1.5.5源代码阅读和编辑
2.8.1 万用表
2.8.2示波器
2.8.3逻辑分析仪
2.9总结
第3章unttx内核及内核编程
3.1linux内核的发展与演变
3.2linux 2.6内核的特点
3.3linux内核的组成
3.3.1linux内核源代码目录结构
3.3.2linux内核的组成部分
3.3.3linux内核空间与用户空间
3.4linux内核的编译及加载
3.4.1linux内核的编译
3.4.2kconfi9和makefile
3.4.3linux内核的引导
3.5linux下的c编程特点
3.5.1linux编码风格
3.5.2gnuc与ansic
3.5.3do{}while(o)
第2篇linux设备驱动核心理论
Linux设备驱动开发详解第二版(1-5章)
/data/612086
Linux设备驱动开发详解第二版ቤተ መጻሕፍቲ ባይዱ6-13章)
/data/612088
Linux设备驱动开发详解第二版(14-18章)
/data/612089
2.3.3 usb
2.3.4以太网接口
2.3.5 isa
2.3.6pci和cpci
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
华清远见
自旋锁:
• •
自旋锁 VS 信号量
忙等待,无调度开销 进程抢占被禁止 锁定期间不能睡觉
spinlock_t lock; spin_lock_init(&lock);
• • •
spin_lock (&lock) ; // 获取自旋锁,保护临界区 . . ./ / 临界区 spin_unlock (&lock) ; // 解锁
信号量
• • • • • • •
拿不到就切换进程,有调度开销 锁定期间可以睡觉,不用于中断上下文
// 定义信号量 DECLARE_MUTEX(mount_sem); down(&mount_sem);// 获取信号量,保护临界区 . . . critical section // 临界区 . . . up(&mount_sem);// 释放信号量
•
•
•
•
•
•
•
•
signal ()绑定
用户空间
f c n t l( f d, F _ S E T O W N, g e t p i d( ) ) f c n t l( f d , F _GE T F L)
信号处理函数
执行 导致
信号
内核设置 filp>f_owner
设备驱动 fasync()函数
等待队列:进程等待被唤醒的一种机制 阻塞与非阻塞使用模板
阻塞非阻塞
华清远见
• • • • • • • • • • • • • • • • • • •
polling
驱动中 POLL 模板
1 static unsigned int xxx_poll(struct file *filp, poll_table *wait) 2 { 3 unsigned int mask = 0; 4 struct xxx_dev *dev = filp>private_data; /* 获得设备结构体指针 */ 6 ... 8 poll_wait(filp, &dev>wait, wait); 9 10 if (...)// 可读 11 { 12 mask |= POLLIN | POLLRDNORM; /* 标示数据可获得 */ 13 } 15 if (...)// 可写 16 { 17 mask |= POLLOUT | POLLWRNORM; /* 标示数据可写入 */ 18 } 19 20 ... 21 return mask; 22 }
释放
资源可获得 内核空间
华清远见
两个半部
上半部 中断 ( 紧急的硬件操作 )
中断
下半部 (延缓的耗时操作 )
机制
tasklet 工作队列
1 /* 定义 tasklet 和底半部函数并关联 */ 2 void xxx_do_tasklet(unsigned long); 3 DECLARE_TASKLET(xxx_tasklet, xxx_do_tasklet, 0);4 5 /* 中断处理底半部 */ 6 void xxx_do_tasklet(unsigned long) 7 {... 9 } 11 /* 中断处理顶半部 */ 12 irqreturn_t xxx_interrupt(int irq, void *dev_id, struct pt_regs *regs) 13 { 15 16 ...} ... tasklet_schedule(&xxx_tasklet);
读写函数
中断 资源可 获得
读写函数
内核空间
资源状态变更 资源状态变更 资源不 可获得 阻塞I/O 资源可 获得 非阻塞轮询 I/O
异步通知
华清远见
1 static ssize_t xxx_write(struct file *file, const char *buffer, size_t count, 2 loff_t *ppos) 3 { 4 ... 5 DECLARE_WAITQUEUE(wait, current); // 定义等待队列 6 add_wait_queue(&xxx_wait, &wait); // 添加等待队列 7 8 ret = count; 9 /* 等待设备缓冲区可写 */ 10 do 11 { 12 avail = device_writable(...); 13 if (avail < 0) 14 __set_current_state(TASK_INTERRUPTIBLE);// 改变进程状态 15 16 if (avail < 0) 17 { 18 if (file>f_flags &O_NONBLOCK) // 非阻塞 19 { 20 if (!ret) 21 ret = EAGAIN; 22 goto out; 23 } 24 schedule(); // 调度其他进程执行 25 if (signal_pending(current))// 如果是因为信号唤醒 26 { 27 if (!ret) 28 ret = ERESTARTSYS; 29 goto out; 30 } 31 } 32 }while (avail < 0); 33 34 /* 写设备缓冲区 */ 35 device_write(...) 36 out: 37 remove_wait_queue(&xxx_wait, &wait);// 将等待队列移出等待队列头 38 set_current_state(TASK_RUNNING);// 设置进程状态为 TASK_RUNNING 39 return ret; 40 }
华清远见
设备访问方式
资源可获得
读写 返回 读写系统 调用 返回 阻塞 读写函数
poll() 或select() 返回 阻塞 poll系统调用
读写 返回 读写系统 调用 返回
信号处理函数 (进行读写 ) 用户空间 signal signal 读写系统调用 系统调用
唤醒 唤醒 唤醒 xxx_func() yyy_func() 中断
华清远见
信号 : 软件意义上的“中断”
异步 I/O
驱动发出信号
kill_fasync(&dev>async_queue, SIGIO, POLL_IN);
•
用户空间应用程序处理信号
24 signal(SIGIO, input_handler); 25 fcntl(STDIN_FILENO, F_SETOWN, getpid()); 26 oflags = fcntl(STDIN_FILENO, F_GETFL); 27 fcntl(STDIN_FILENO, F_SETFL, oflags | FASYNC); 8 void input_handler(int num) 9 { ... 14 len = read(STDIN_FILENO, &data, MAX_LEN); 15 ... }
华清远见
Linux 设备驱动的现状
高需求
Linux 内核的绝大多数代码为设备驱动 新设备、新芯片、新驱动的需求
高门槛
涉及到大量硬件操作 涉及到内核基础知识 涉及到并发控制与同步 复杂的软件结构框架
高回报
华清远见
从 nonos 驱动到 Linux 驱动
•
• • • • • • • • •
位原子操作
•
设置 / 清除 / 反转位 void set_bit(nr, void *addr); void clear_bit(nr, void *addr); void change_bit(nr, void *addr); 测试位 test_bit(nr, void *addr); η 测试并操作位 int test_and_set_bit(nr, void *addr); int test_and_clear_bit(nr, void *addr); int test_and_change_bit(nr, void *addr);
串口
LED
FLASH
硬件
nonos 驱动与应用
onos 驱动与应用
华清远见
并发和竞态
并发和竞态:
对称多处理器 ( SMP )的多个 CPU 单 CPU 内进程与抢占它的进程 中断(硬中断、软中断、 Tasklet 、底半部)与进程之间
处理思路:
常用方法 :
lock() // 锁定,拿虎符 . . . critical section // 临界区,调动军队 . . . unlock() // 解锁定,归还虎符
中断屏蔽 原子操作 自旋锁 信号量 互斥体
华清远见
接口 • 整型原子操作
• • • • • • • • • • • • • • • • • • • •
嵌入式培训专家
Linux 设备驱动开发
华清远见
今天的内容
Linux 设备驱动的现状 从 nonos 驱动到 Linux 驱动 内核设施 自旋锁、信号量、互斥量、完成量 异步通知、信号 阻塞与非阻塞 内存与 I/O 操作, DMA 中断, top half/bottom half 字符设备驱动 复杂设备驱动的框架 LCD 设备 FRAMEBUFFER FLASH 设备 MTD TTY 设备 块设备 用户空间的设备驱动 设备驱动开发流程 开发环境建设 调试手段 用户空间测试 设备驱动的学习方法
• • • • • • • •
用户空间 POLL 模板
fd_set fds; FD_ZERO(&fds); FD_SET(fd, &fds); select(fd + 1, &rfds, &wfds, NULL, NULL); if (FD_ISSET(fd, &fds)) { printf("Poll monitor:can be access\n"); }