linux驱动开发重要知识点
① linux驱动开发要有哪些基础
需要一定的努力才可以学好:
Linux设备驱动是linux内核的一部分,是用来屏蔽硬件细节,为上层提供标准接口的一种技术手段。为了能够编写出质量比较高的驱动程序,要求工程师必须具备以下几个方面的知识:
1、 熟悉处理器的性能
如:处理器的体系结构、汇编语言、工作模式、异常处理等。对于初学者来说,在还不熟悉驱动编写方法的情况下,可以先不把重心放在这一项上,因为可能因为它的枯燥、抽象而影响到你对设备驱动的兴趣。随着你不断地熟悉驱动的编写,你会很自然的意识到此项的重要性。
2、掌握驱动目标的硬件工作原理及通讯协议
如:串口控制器、显卡控制器、硬件编解码、存储卡控制器、I2C通讯、SPI通讯、USB通讯、SDIO通讯、I2S通讯、PCI通讯等。编写设备驱动的前提就是需要了解设备的操作方法,所以这些内容的重要程度不言而喻。但不是说要把所有设备的操作方法都熟悉了以后才可以写驱动,你只需要了解你要驱动的硬件就可以了。
一、掌握硬件的控制方法
如:中断、轮询、DMA 等,通常一个硬件控制器会有多种控制方法,你需要根据系统性能的需要合理的选择操作方法。初学阶段以实现功能为目的,掌握的顺序应该是,轮询->中断->DMA。随着学习的深入,需要综合考虑系统的性能需求,采取合适的方法。
二、良好的GNU C语言编程基础
如:C语言的指针、结构体、内存操作、链表、队列、栈、C和汇编混合编程等。这些编程语法是编写设备驱动的基础,无论对于初学者还是有经验者都非常重要。
三、 良好的linux操作系统概念
如:多进程、多线程、进程调度、进程抢占、进程上下文、虚拟内存、原子操作、阻塞、睡眠、同步等概念及它们之间的关系。这些概念及方法在设备驱动里的使用是linux设备驱动区别单片机编程的最大特点,只有理解了它们才会编写出高质量的驱动。
四、掌握linux内核中设备驱动的编写接口
如:字符设备的cdev、块设备的gendisk、网络设备的net_device,以及基于这些基本接口的framebuffer设备的fb_info、mtd设备的mtd_info、tty设备的tty_driver、usb设备的usb_driver、mmc设备的mmc_host等。
② 想学习Linux 驱动,需要什么知识
首先,接触linux操作系统,在你的电脑上装一个linxu操作系统(建议ubuntu,比
较友好),熟悉经常要用的命令,熟悉环境(建议看“鸟哥的linux私房菜”)。
其次,阅读经典书籍是不可少的,建议先看ldd前四章,大概了解linux驱动的框架
,驱动是做什么的,该如何写驱动,那本书上有一些例子,可以在你的电脑上编译
,执行看看。后面的章节在结合自己的情况而定。
第三,建议阅读ulk(understanding the linux kernel)所有的内容,了解linux
内核的一些基本知识,在心中建立一个框架,不必完全懂,深入了解就好,以后经
常翻翻,受益无穷!
第四,别着急,这才是你真的进入linux驱动的第一步,花点钱买个开发板吧,然
后了解代码的编译,下载,看看板子的datasheet,针对自己感兴趣的深入研究。
建议学习流程,led灯控制---tp---i2c总线-----lcd-----camera----flash----
wifi/bt等。因为这个里面牵涉了甚多内核的子系统(input,v4l2,fb等
),所以可能要多话时间看代码,了解代码的框架,设计的思想等,只要一步一个
脚印,一定会有所成。
第五,因为现在的移动设备大多数都是android的了,所以你就要看看linux
kernel在android的作用,然后往上看看,看看hal层的代码,这些在调试中都是需
要的,如果有兴趣,更加可以看看framework的代码了,学习android一些工作机制
,类似于surfaceflinger,audioflinger等等。。
《linux就该这么学》免费提供最新Linux技术教程书籍,为开源技术爱好者努力做
得更多更好
③ 如何系统的学习Linux驱动开发
在学习之前一直对驱动开发非常的陌生,感觉有点神秘。不知道驱动开发和普通的程序开发究竟有什么不同;它的基本框架又是什么样的;他的开发环境有什么特殊的地方;以及怎么写编写一个简单的字符设备驱动前编译加载,下面我就对这些问题一个一个的介绍。
一、驱动的基本框架
1.那么究竟什么是驱动程序,它有什么用呢:
l驱动是硬件设备与应用程序之间的一个中间软件层
l它使得某个特定硬件能够响应一个定义良好的内部编程接口,同时完全隐蔽了设备的工作细节
l用户通过一组与具体设备无关的标准化的调用来完成相应的操作
l驱动程序的任务就是把这些标准化的系统调用映射到具体设备对于实际硬件的特定操作上
l驱动程序是内核的一部分,可以使用中断、DMA等操作
l驱动程序在用户态和内核态之间传递数据
2.Linux驱动的基本框架
3.Linux下设备驱动程序的一般可以分为以下三类
1)字符设备
a)所有能够象字节流一样访问的设备都通过字符设备来实现
b)它们被映射为文件系统中的节点,通常在/dev/目录下面
c)一般要包含open read write close等系统调用的实现
2)块设备
d)通常是指诸如磁盘、内存、Flash等可以容纳文件系统的存储设备。
e)块设备也是通过文件系统来访问,与字符设备的区别是:内核管理数据的方式不同
f)它允许象字符设备一样以字节流的方式来访问,也可一次传递任意多的字节。
3)网络接口设备
g)通常它指的是硬件设备,但有时也可能是一个软件设备(如回环接口loopback),它们由内核中网络子系统驱动,负责发送和接收数据包。
h)它们的数据传送往往不是面向流的,因此很难将它们映射到一个文件系统的节点上。
二、怎么搭建一个驱动的开发环境
因为驱动是要编译进内核,在启动内核时就会驱动此硬件设备;或者编译生成一个.o文件,当应用程序需要时再动态加载进内核空间运行。因此编译任何一个驱动程序都要链接到内核的源码树。所以搭建环境的第一步当然是建内核源码树
1.怎么建内核源码树
a)首先看你的系统有没有源码树,在你的/lib/ moles目录下会有内核信息,比如我当前的系统里有两个版本:
#ls /lib/ moles
2.6.15-rc72.6.21-1.3194.fc7
查看其源码位置:
## ll /lib/moles/2.6.15-rc7/build
lrwxrwxrwx 1 root root 27 2008-04-28 19:19 /lib/moles/2.6.15-rc7/build -> /root/xkli/linux-2.6.15-rc7
发现build是一个链接文件,其所对应的目录就是源码树的目录。但现在这里目标目录已经是无效的了。所以得自己重新下载
b)下载并编译源码树
有很多网站上可以下载,但官方网址是:
http://www.kernel.org/pub/linux/kernel/v2.6/
下载完后当然就是解压编译了
# tar –xzvf linux-2.6.16.54.tar.gz
#cd linux-2.6.16.54
## make menuconfig (配置内核各选项,如果没有配置就无法下一步编译,这里可以不要改任何东西)
#make
…
如果编译没有出错。那么恭喜你。你的开发环境已经搭建好了
三、了解驱动的基本知识
1.设备号
1)什么是设备号呢?我们进系统根据现有的设备来讲解就清楚了:
#ls -l /dev/
crwxrwxrwx 1 root root1,3 2009-05-11 16:36 null
crw------- 1 root root4,0 2009-05-11 16:35 systty
crw-rw-rw- 1 root tty5,0 2009-05-11 16:36 tty
crw-rw---- 1 root tty4,0 2009-05-11 16:35 tty0
在日期前面的两个数(如第一列就是1,3)就是表示的设备号,第一个是主设备号,第二个是从设备号
2)设备号有什么用呢?
l传统上,主编号标识设备相连的驱动.例如, /dev/null和/dev/zero都由驱动1来管理,而虚拟控制台和串口终端都由驱动4管理
l次编号被内核用来决定引用哪个设备.依据你的驱动是如何编写的自己区别
3)设备号结构类型以及申请方式
l在内核中, dev_t类型(在中定义)用来持有设备编号,对于2.6.0内核, dev_t是32位的量, 12位用作主编号, 20位用作次编号.
l能获得一个dev_t的主或者次编号方式:
MAJOR(dev_t dev); //主要
MINOR(dev_t dev);//次要
l但是如果你有主次编号,需要将其转换为一个dev_t,使用: MKDEV(int major, int minor);
4)怎么在程序中分配和释放设备号
在建立一个字符驱动时需要做的第一件事是获取一个或多个设备编号来使用.可以达到此功能的函数有两个:
l一个是你自己事先知道设备号的
register_chrdev_region,在中声明:
int register_chrdev_region(dev_t first, unsigned int count, char *name);
first是你要分配的起始设备编号. first的次编号部分常常是0,count是你请求的连续设备编号的总数. name是应当连接到这个编号范围的设备的名子;它会出现在/proc/devices和sysfs中.
l第二个是动态动态分配设备编号
int alloc_chrdev_region(dev_t *dev, unsigned int firstminor, unsigned int count, char *name);
使用这个函数, dev是一个只输出的参数,它在函数成功完成时持有你的分配范围的第一个数. fisetminor应当是请求的第一个要用的次编号;它常常是0. count和name参数如同给request_chrdev_region的一样.
5)设备编号的释放使用
不管你是采用哪些方式分配的设备号。使用之后肯定是要释放的,其方式如下:
void unregister_chrdev_region(dev_t first, unsigned int count);
6)
2.驱动程序的二个最重要数据结构
1)file_operation
倒如字符设备scull的一般定义如下:
struct file_operations scull_fops = {
.owner = THIS_MODULE,
.llseek = scull_llseek,
.read = scull_read,
.write = scull_write,
.ioctl = scull_ioctl,
.open = scull_open,
.release = scull_release,
};
file_operation也称为设备驱动程序接口
定义在,是一个函数指针的集合.每个打开文件(内部用一个file结构来代表)与它自身的函数集合相关连(通过包含一个称为f_op的成员,它指向一个file_operations结构).这些操作大部分负责实现系统调用,因此,命名为open, read,等等
2)File
定义位于include/fs.h
struct file结构与驱动相关的成员
lmode_t f_mode标识文件的读写权限
lloff_t f_pos当前读写位置
lunsigned int_f_flag文件标志,主要进行阻塞/非阻塞型操作时检查
lstruct file_operation * f_op文件操作的结构指针
lvoid * private_data驱动程序一般将它指向已经分配的数据
lstruct dentry* f_dentry文件对应的目录项结构
3.字符设备注册
1)内核在内部使用类型struct cdev的结构来代表字符设备.在内核调用你的设备操作前,必须编写分配并注册一个或几个这些结构.有2种方法来分配和初始化一个这些结构.
l如果你想在运行时获得一个独立的cdev结构,可以这样使用:
struct cdev *my_cdev = cdev_alloc();
my_cdev->ops = &my_fops;
l如果想将cdev结构嵌入一个你自己的设备特定的结构;你应当初始化你已经分配的结构,使用:
void cdev_init(struct cdev *cdev, struct file_operations *fops);
2)一旦cdev结构建立,最后的步骤是把它告诉内核,调用:
int cdev_add(struct cdev *dev, dev_t num, unsigned int count);
说明:dev是cdev结构, num是这个设备响应的第一个设备号, count是应当关联到设备的设备号的数目.常常count是1,但是有多个设备号对应于一个特定的设备的情形.
3)为从系统去除一个字符设备,调用:
void cdev_del(struct cdev *dev);
4.open和release
④ 嵌入式linux驱动要学哪些
1、 编写Linux设备驱动要求工程师有非常好的硬件基础,懂得SRAM、Flash、SDRAM、磁盘的读写方式,UART、I2C、USB等设备的接口以及轮询、中断、DMA的原理,PCI总线的工作方式以及CPU的内存管理单元(MMU)等。
2、编写Linux设备驱动要求工程师有非常好的C语言基础,能灵活地运用C语言的结构体、指针、函数指针及内存动态申请和释放等。
3、编写Linux设备驱动要求工程师有一定的Linux内核基础,虽然并不要求工程师对内核各个部分有深入的研究,但至少要明白驱动与内核的接口。尤其是对于块设备、网络设备、Flash设备、串口设备等复杂设备,内核定义的驱动体系架构本身就非常复杂。
4、编写Linux设备驱动要求工程师有非常好的多任务并发控制和同步的基础,因为在驱动中会大量使用自旋锁、互斥、信号 量、等待队列等并发与同步机制。朱,有,鹏的驱动开发讲得还不错。
⑤ 嵌入式Linux驱动程序开发学习路线
关于这个方向,我认为大概分3个阶段:
1、嵌入式linux上层应用,包括QT的GUI开发
2、嵌入式linux系统开发
3、嵌入式linux驱动开发
嵌入式目前主要面向的几个操作系统是,LINUX,WINCE、VxWorks等等
Linux是开源免费的,而且其源代码是开放的,更加适合我们学习嵌入式。
所以你可以尝试以下路线:
(1)C语言是所有编程语言中的强者,单片机、DSP、类似ARM的种种芯片的编程都可以用C语言搞定)神数,因此必须非常熟练的掌握。
推荐书籍:《TheCProgrammingLanguage》这本经典的教材是老外写的,也有中译版本。
(2)操作系统原理,是必需的,如果你是计算机专业毕业那也就无所谓了,如果是非计算机专业的就必须找一本比较浅显的计算机原理书籍看一看,把啥叫“进程”“线程”“系统调度”等等基本问题搞清楚。
(3)Linux操作系统就是用C语言编写的,所以你也应该先学习下Linux方面的编程,只有你会应用了,才能近一步去了解其内核的精髓。
推荐书籍:《UNIX环境高级编程》(第2版)
(4)了解ARM的架构,原理,以及其汇编指令,我们在嵌入式开发中,一般很少去写汇编,但是最起码的要求是能够看懂arm汇编。
(5)系统移植的时候,就需要你从最下层的bootloader开始,然后内核移植,文件系统移植等。而移植这部分对硬件的依赖是非常大的,其配置步骤也相对复杂,也没有太多详细资料。
(6)驱动开发
linux驱动程序设计既是个极富有挑战性的领域,又是一个博大精深的内容。
linux驱动程序设计本质是属于linux内核编程范畴的,因而是对linux内核和内核编程是有要求的。在学习前你要想了解linux内核的组成,因为每一部分要详细研究的话足够可以扩展成一本厚书。
以上只不过是大概的框架,在实际的开发中还会涉及很多东西,比如:交叉编译、makefile、shell脚本等等,所以说学习嵌入式的周期较长,门槛较高,自学的话更是需要较强的学习能力和专业功底。只要能坚持下来一定会取得成功!
嵌入式非常难,看书的话比较晦涩难懂,不容易入门,我个人比较偏向于看视频教程,因为有老师带着比较容易入门。给看看一篇文章是关于一位专科生怎么自学嵌入式的。
做个自我介绍,我07年考上一所很烂专科民办的学校,学的是生物专业,具体的学校名称我就不说出来献丑了。09年我就辍学了,我在那样的学校,一年学费要1万多,但是根本没有人学习,我实在看不到希望,我就退学了。
退学后我也迷茫,大专都没有毕业,我真的不知道我能干什么,我在纠结着我能做什么。所以辍学后我一段时间,我想去找工作,因为我比较沉默寡言,不是很会说话,我不适合去应聘做业务。我想应聘做技术的,可是处处碰壁。
一次偶然的机会,我才听到嵌入式这个行业。那天我去新华书店,在计算机分类那边想找本书学习。后来有个女孩子走过来,问我是不是读计算机的,有没有兴趣学习嵌入式,然后给我介绍了一下嵌入式现在的火热情况,告诉我学嵌入式多么的有前景,给我了一份传单,嵌入式培训的广告。听了她的介绍,我心里痒痒的,确实我很想去学会一门自己的技术,靠自己的双手吃饭。
回家后,我就上网查了下嵌入式,确实是当今比较热门的行业,也是比较好找工作的,工资也是相对比较高。我就下决心想学嵌入式了。于是我去找嵌入式培训的相关信息,说真的,我也很迷茫,我不知道培训是否真的能像他们宣传的那样好,所以我就想了解一段时间再做打算。
后来,我在网络知道看到一篇让我很鼓舞的游兆首文章,是一个嵌入式猜姿高手介绍没有基础的朋友怎么自学入门学嵌入式,文章写的很好,包含了如何学习,该怎么学习。他提到一个方法就是看视频,因为看书实在太枯燥和费解的,很多我们也看不懂。这点我真的很认同,我自己看书往往看不了几页。
我在想,为什么别人都能自学成才,我也可以的!我要相信自己,所以我就想自学,如果实在学不会我再去培训。
主意一定,我就去搜索嵌入式的视频,虽然零星找到一些嵌入式的视频,但是都不系统,我是想找一个能够告诉我该怎么学的视频,一套从入门到精通的视频,一个比较完整的资料,最好能有老师教,不懂可以请教的。
后来我又找到一份很好的视频,是在IT学习联盟网站推出的一份视频《零基础嵌入式就业班》(喜欢《零基础嵌入式就业班》的可以复制sina.lt/qKh粘贴浏览器按回车键即打开)。里面的教程还不错,很完整,可以让我从基础的开始学起。视频比较便宜。
下面介绍下我的学习流程,希望对和我一样完全没有基础的朋友有所帮助。
收到他们寄过来的光盘后,我就开始学习了,由于我没有什么基础,我就从最简单的C语言视频教程学起,话说简单,其实我还是很多不懂的,我只好请教他们,他们还是很热心的,都帮我解决了。C语言我差不多学了一个礼拜,接下来我就学了linux的基本命令,我在他们提供linux虚拟机上都有做练习,敲linux的基本命令,写简单的C语言代码,差不多也就三个礼拜。我每天都在不停的写一些简单的代码,这样一月后我基本掌握了C和linux的基本操作。
接下来我就去学习了人家的视频的培训教程,是整套的,和去参加培训没有多大的区别,这一看就是两个月,学习了ARM的基本原理,学习嵌入式系统的概念,也掌握了嵌入式的环境的一些搭建,对linux也有更深层次的理解了,明白了嵌入式应用到底是怎么做的,但是驱动我只是有一点点的了解,这个相对难一点,我想以后再慢慢啃。
这两个月,除了吃饭睡觉,我几乎都在学习。因为我知道几乎没有基础,比别人差劲,我只能坚持努力着,我不能放弃,我必要要靠自己来养活自己,必须学好这门技术,然后我就把不懂的问题总结记下来,这样慢慢积累了一段时间,我发现自己真的有点入门了。
最后的一个月,我就去看关于实践部分的内容,了解嵌入式项目具体的开发流程,需要什么样的知识,我就开始准备这方面的知识,也就是学习这方面的视频,同时他们建议我去找了找一些嵌入式面试的题目,为自己以后找工作做准备。我就到网上找了很多嵌入式的题目,把他们理解的记下来,这样差不多准备了20天左右
我觉得自己差不多入门了,会做一些简单的东西了。我就想去找工作看看,于是我就到51job疯狂的投简历,因为我学历的问题,专科没有毕业,说真的,大公司没有人会要我,所以我投的都是民营的小公司,我希望自己的努力有所回报。没有想过几天过后,就有面试了,但是第一次面试我失败了,虽然我自认为笔试很好,因为我之前做了准备,但是他们的要求比较严格,需要有一年的项目经验,所以我没有被选中。
后来陆续面试了几家公司,终于功夫不负有心人。我终于面试上的,是在闵行的一家民营的企业,公司规模比较小,我的职务是嵌入式linux应用开发,做安防产品的应用的。我想我也比较幸运,经理很看重我的努力,就决定录用我,开的工资是3500一个月,虽然我知道在上海3500只能过温饱的生活,但是我想我足够了。我至少不用每天都要靠父母养,我自己也能养活自己的。我想只要我继续努力,我工资一定会翻倍的。
把本文写出来,希望能让和我一样的没有基础的朋友有信心,其实我们没有必要自卑,我们不比别人笨,只要我们肯努力,我们一样会成功。
⑥ 如何自学linux驱动开发,做驱动开发需要哪些方面的知识
硬件接口标准(参阅有关总线,设备控制器的技术文档)
操作系统的设备无关的部分
也就是说 驱动位于硬件和设备无关软件之间,向下屏蔽设备的硬件细节,向上为操作系统IO管理机制提供具体的策略。
一者,你即要有系统结构的常识,又要有IO软件层次的常识
二者,必须和参阅硬件接口标准,必须懂操作系统的IO管理的机制。
所以,驱动的编写,即与硬件细节打交道,有和具体的操作系统打交道。
驱动的编写模式单一,只要你啃下这些东西,就OK了,相对而言,不如应用软件难做,只是不少人对系统没有较为深入的理解罢了。