`
shinfocom
  • 浏览: 1188178 次
文章分类
社区版块
存档分类
最新评论

Linux下第一个驱动程序

 
阅读更多

因为在Ubuntu环境下写的文章和做的实验,没有安装linux下比较好用的截图工具,所以没有附带太多截屏,还望海涵,不过该描述的都到位了。

曾经还一直处于应用程序开发的我,以为驱动开发者是那么的厉害,以为只有牛人才能走到这一步,随着知识的积累,发现并非如此,驱动开发并不像想象中那么特别,俗话说术业有专攻,开发者只是使用的工具不同,且从事的领域不同,产品不同罢了。只要能作出好的产品,你就是一个”牛人”。

从这里开始进行系统化的驱动学习,主线是《Linux设备驱动开发详解》,之前大致看过这本书,起初感觉有些晦涩,但看了两本内核的书籍以后,重新回来读起来就比较顺流了,一口气读了好几章(主要是前几章是知识介绍性文章)。所以这里顺便推荐两本内核的书籍:

《Linux内核设计与实现》,我看的是第二版,写的非常棒,简单易懂,要在介绍内核原理与实现机制,广度到了,深度不够,所以最好还得配合下边这本书一块儿看。

《UnderstandingLinux kernel》——深入理解linux内核,这本书的第三版是基于2.6内核的,06年出版。我看的是英文原版的,所以看得速度比较满,不过正好和《Linux设备驱动开发详解》对接上了,刚看过《Understanding Linux kernel》中的同步异步,应该是第五章那里,然后《Linux设备驱动开发详解》就在第七章也讲到了,这样,可能那么多机制:锁,读写锁,顺序锁,信号量,读写信号量……一下出来这么多东西的话有些接受不了,但如果你之前看了《Linux内核设计与实现》后,最起码不会感觉恐慌,其实学习新的知识就是这样,一回生两回熟,再难理解的东西,功夫到了,也就理解了。

好的,开始第一个驱动程序的学习,实例来自 Linux设备驱动开发详解,这里是创建了一个虚拟的字符设备globalmem,也就是一片内核空间的内存区域,来实现内核空间和用户空间的信息传递。(确实,我举不出来比这更好的例子来作第一个例子了,不过请相信,哪怕就是这个例子也是我一个字母一个字母敲出来的,并未直接取材自隋书的源码,主要是看我的注释,和我遇到的问题以及解决它的全过程,成功者找方法,失败者找借口!呵呵)

不废话,上代码,别心急,看注释。。。

下边是驱动的源码,附上了详尽的注释:

globalmem.c



Makefile的写法和前面一篇文章的helloworld的模块的Makefile写法一致,换个模块的名字而已,这里是:




准备好后开始进行编译,就是make一下就OK ;

make时又遇到了这样的问题:

make:Nothing to be done for 'all'.

Makeclearn 时也会出现:

make:Nothing to be done for 'clearn'.

网上说的都是一编译好了,只是没有修改源文件,所以没有进行再编译(我知道这也是make存在的理由,它的一方面功能就是这样的,避免重复编译未修改的文件),但显示是它确实不存在这个问题,我小纠结了一下,并且也没有其他任何编译时的报错提示。为了做测试,我又试着编译之前的helloworld的模块,终于报错了,哈哈哈。问题在于,make中的make -C /usr/src/linux-headers-$(shell uname -r) M=$(shell pwd)modules ,该命令是动态的通过shell命令的uname来获取当前内核源码路径,并进行连接编译驱动的。而我下载并构建的内核是:2.6.32-30-generic,而此时系统装载的是(也就是uname -r命令得到的内核版本):2.6.30-27-generic,而该版本的内核源码树我已经手动删除,所以我的源码路径和通过uname -r组装出来的是不一致的,所以我把Makefile中的命令手动修改成了:

make -C /usr/src/linux-headers-2.6.32-30-generic M=$(shell pwd) modules ,直接指定路径(这样的可维护性下降了,不过我们的工程太小,可以忽略这个问题)。OK ,try again,make 通过了,目录下编译出来了那群你梦寐以求想看到的文件们,他们这时显得是如此的可爱。

这里还要说的是,模块只是一种把自己的代码动态加载到内核的手段,这也就说明了为什么我的驱动模块的Makefile文件为何和helloworld模块的Makefile文件是一模一样的(确实,模块的名字是不一样的,你知道我是什么意思),所以对于驱动来说,模块就是一条小船,它把代码运载到了kernel所在的海域,作为一个载体把驱动的代码带到了内核空间,从而使得你在用户空间调用某些系统操作时,OS可以找到对应的代码来完成你的请求。

好的,编译好了,就该装载并测试了。

$ insmod globalmem.ko #“Ubuntu下必要时记着加sudo,因为我已经开启了ubuntu的su”

呵呵,又来错误了。看来又要成长了,要善待你碰到的没一个失败,毕竟她是成功他妈。

装载时报错了:

insmod:error inserting 'globalmem.ko': -1 Invalid module format

还是因为我系统现装载的内核和对模块进行编译的内核版本不一致造成的,所以,我得把在构建的内核源码树中版本较新的内核安装到系统中去才行。这里安装新内核的方法,可以借鉴这篇博文(哈哈,我越来越爱西邮的学生了,如果你想考研或者招聘,西邮出来的做linux的都是非常棒的。额,作广告了,呵呵):http://edsionte.com/techblog/archives/3289/comment-page-1#comment-2350

一切就绪,有装载过对应版本的内核后,重启一下,进入对应的内核版本中去。重新insert our module ,try again。

$ insmod globalmem.ko

welldone,we've already made it.好的,接下来在用户空间测试一下。

驱动是针对设备而言的(虽然这里的设备并非是实实在在的,只是一片内存),而linux下的设备又都是抽象成文件来看待的(毕竟unix最早是从一个文件系统演变过来的,也就是这一壮举,使得驱动的开发容易多了,统一的抽象带来了非常大的方便)。所以我们要把这个设备文件创建出来。

$ mknod /dev/globalmem c 250 0 #创建一个主设备号为250次设备号是0的字符设备文件globalmem到/dev下。

然后就可以开始测试了:

$ echo“Hello jun” > /dev/globalmem #写“hello jun”到设备

提示:

bash:/dev/globalmem: Permission denied

权限不够,ls -l 发现:

crw-r--r--1 root root 250, 0 Oct 20 15:47 /dev/globalmem

你要么用sudo来echo,要么把文件权限该一下,这个自由留给你了。呵呵

$ cat /dev/globalmem #显示设备文件的内容

显示如下:



root@jun-desktop:/home/jun/driver/ch6#cat /dev/globalmem

hellojun

好的,大功告成!!!

后记说明:

1、做驱动的话,建议可以在原生的linux环境下,其实也挺方便的。

2、推荐一个c/c++的IDE吧——Code:Blocks ,挺好用的集成开发环境,只是第一次用它就喜欢上了,不过和SCIM输入法稍有冲突,注释的时候要输入中文,如果中文文字删减时,会出现打不上中文的情况,要调成英文状态再调回中文状态才能继续。

另外,它带有语句联想功能,当然是只支持用户空间c函数库德联想,不支持kernel中的函数或结构。个人感觉要比Vi用着来的有效率些,呵呵

3、 对于echo 是“!”的问题。截屏中可以看到,要输出!还要进行转义字符转义。

4、从文章可以看出,作者我确实够笨,每次记录都会碰见如此多的看似比较弱智的问题,好在找到了解决办法,详尽写实的记录比较符合本人博客的特色。

5、编写和编译该驱动的环境并非前边文章介绍的虚拟机环境,是本机硬盘上的Ubuntu10.04,在我机器上有些时日了,忘了内核版本才凸显了上边遇到的很多问题,unlikely(你的开发过程中不会遇到类似的装载内核和编译内核不协调的情况);不过你可能会在其他地方遇到,遇到是千万别说没见过而束手无策。

6、提前把第一个驱动实验的记录过程发blog了,驱动相关的知识还没有内容介绍,可能和前边知识不太衔接,得花谢时间尽快补上。不过希望读者和我同步一起不断积累内核体系的相关知识,非常方便理解的。



【本文doc文档下载及源码下载】

分享到:
评论

相关推荐

    linux驱动程序第一个驱动-按键点亮LED

    linux驱动程序第一个驱动-按键点亮LED linux驱动程序第一个驱动-按键点亮LED linux驱动程序第一个驱动-按键点亮LED linux驱动程序第一个驱动-按键点亮LED

    精通LINUX设备驱动程序开发

    第1章 引言   第2章 内核   第3章 内核组件   第4章 基本概念   第5章 字符设备驱动程序   第6章 串行设备驱动程序   第7章 输入设备驱动程序   第8章 I2C协议  第9章 PCMCIA和CF   第10...

    精通Linux设备驱动程序开发

    第1章 引言 第2章 内核 第3章 内核组件 第4章 基本概念 第5章 字符设备驱动程序 第6章 串行设备驱动程序 第7章 输入设备驱动程序 第8章 I2C协议 第9章 PCMCIA和CF 第10章 PCI 第11章 USB 第12章 视频...

    Linux简单驱动程序

    史上最简单的第一个linux驱动程序,用来学习驱动入门很不错。

    编写第一个嵌入式Linux驱动程序

    编写第一个嵌入式Linux驱动程序,申嵌视频-入门篇

    《精通Linux 设备驱动程序开发》.(Sreekrishnan).pdf

    第1章 引言1 1.1 演进1 1.2 gnu copyleft2 1.3 kernel.org2 1.4 邮件列表和论坛3 1.5 linux发行版3 1.6 查看源代码4 1.7 编译内核7 1.8 可加载的模块8 1.9 整装待发9 第2章 内核11 2.1 启动...

    教你写第一个LINUX设备驱动程序

    教你写第一个LINUX设备驱动程序,这是一个完整的程序,以及他的编译过程。

    国嵌培训课件Linux驱动程序设计

    第一天 1.Linux驱动简介 2.字符设备驱动程序设计 3.驱动调试技术 4. 并发与竞态 第二天 1.Ioctl型驱动 2.内核等待队列 3. 阻塞型驱动程序设计 4.Poll设备操作 第三天 1.Mmap设备操作 2. 硬件访问 3. 混杂...

    LINUX设备驱动程序

    LINUX设备驱动程序 内容简介  《LINUX设备驱动程序(第3版)》已针对Linux内核的2610版本彻底更新过了。... 前言 第一章设备驱动程序简介 设备驱动程序的作用 内核功能划分 设备和模块的分类 安全问题

    LINUX设备驱动程序.pdf.pdf

    经典的LINUX设备驱动...他在 1993 年第一次接触 Linux 系统,从 此以后一直从事 Linux 的开发。Corbet 先生是 Linux Weekly News (http://LWN.net) 的奠基人和执行主编;他和妻子及两个孩子生活在科罗拉多州巨石市。

    读书笔记-LINUX设备驱动程序(第3版).pdf

    《Linux 设备驱动程序》第三版是一本面向Linux驱动开发的经典教程,内容非常全面,非常适合没有接触过Linux驱动开发的新手。本人通过阅读本书,对其内容进行了梳理总结,分为两大部分:1.驱动代码分析 2.知识点总结...

    LINUX 设备驱动程序(第二版)

    第1章 Linux内核简介 第2章 编写和运行模块 第3章 字符设备驱动程序 第4章 调试技术 第5章 字符设备驱动程序的扩展操作 第6章 时间流 第7章 获取内存 第8章 硬件管理 第9章 中断处理 第10章 合理使用数据类型 第11章...

    Linux设备驱动程序(中文版第三版).pdf

    Linux设备驱动程序第三版 本书指导你如何编写你自己的驱动, 以及如何利用内核相关的部分. 我们采用一种设备-独立的方法; 编程技术和接口, 在任何可能的时候, 不会捆绑到任何特定的设备. 每一个驱动都是不同的; 作为...

    linux设备驱动程序第三版 示例代码

    linux设备驱动程序第三版 示例代码 大家都懂得,超级经典的一本书代码,俗称LDD3

    Linux设备驱动程序开发详解

    《Linux设备驱动开发详解》是一本介绍Linux设备驱动开发理论、框架与实例的书,《Linux设备驱动开发详解(第2版)》基于LDD6410开发板,以Linux2.6 版本内核为蓝本,详细介绍自旋锁、信号量、完成量、中断顶/底半部、...

    嵌入式Linux驱动程序设计从入门到精通.part01.rar

    CHA1 第一个驱动与测试程序 CHA2 1 信号量同步 2 阻塞式读写 3 定时器 4 内存映射 5 /proc访问 6 工作队列 CHA3 LED.c LED灯驱动 button.c 键盘驱动 CHA4 Linux内核I2C驱动 CHA5 usb-skeleton.c USB驱动框架 ...

    Linux设备驱动详解第二版

    第1章 Linux设备驱动概述及开发环境构建 2 第2章 驱动设计的硬件基础 21 第3章 Linux内核及内核编程 53 第2篇 Linux设备驱动核心理论 第4章 Linux内核模块 82 第5章 Linux文件系统与设备文件系统 92...

    LDD linux设备驱动程序第三版 中文

    linux设备设备驱动程序第三版 是中文的 出版社是中国电力出版社。这是一本学习linux设备驱动开发很经典的书籍。

Global site tag (gtag.js) - Google Analytics