Linux驱动编程 step-by-step (一)驱动程序的作用

转载 2012年03月21日 10:11:02

http://blog.csdn.net/jshazk1989?viewmode=contents


第三次看了LDD3了(虽然现在已经是kernel3.0但从这本书商还是能学到很多) 每次都有一些收获 现在终于能够些一些代码了

驱动程序的作用:

简单来说 驱动程序就是使计算机与设备通信的特殊的代码,在作单片机时候(无OS)我们自己定义接口及自定义的结构来操作相关硬件,而在有OS的模式下我们操作的硬件是去实现对应的接口(这些接口是已定义好的,我们需要实现这些接口)而无需自己定义接口,这样既能正确的控制设备。又能很好的维护(如果需要升级驱动,上边的应用程序不需要改变)

编写驱动考虑的因素

  1. 提供给用户更多的选项
  2. 保持用户操作的简单性
  3. 编写驱动的时间

驱动分类:

  1. 字符设备:能够像字节流(类似文件)一样被访问的设备(至少实现open, close, read ,write等功能)
  2. 快设备:    用户空间接口与字符设备相同, 内部实与字符设备完全不同(可以被随即访问,一般在类UNIX系统中快设备的读取每次只能读一整块在linux可以操作任意字节)
  3. 网络设备:网络通路通过网络设备形成,能够与主机交换数据的设备

内核功能划分:

  1. 进程管理(PM):进程的创建与撤销,在单个或者多个CPU上实现多进程的抽象
  2. 内存管理(MM):管理内存分配及回收的策略
  3. 文件系统(FS/VFS): Linux 非常依赖于文件系统,内核在没有结构的硬件系统上构造结文件系统,而文件抽象在整个系统中会广泛使用,Linux支持多种文件系统类型
  4. 设备控制:驱动程序,操控硬件以及相应总线设备
  5. 网络(NET): 在网络接口于应用程序之间传输数据。

好了 理论行得东西介绍的差不多了,下边说点有用的,内核的驱动可以做成模块在需要的时候装载,在不需要的时候卸载
我们在编写用户程序的时候总喜欢从编写hello world 写起 , 在内核驱动模块也是一样,下边是一个hello_world的一个模块

  1. //hello_world.c   
  2. #include <linux/init.h>   
  3. #include <linux/module.h>  
  4. MODULE_LICENSE("GPL");   
  5.   
  6. static int hello_init(void)   
  7. {   
  8.     printk(KERN_ALERT "hello module\n");   
  9.     return 0;   
  10. }   
  11.   
  12. static void hello_exit(void)   
  13. {   
  14.     printk(KERN_ALERT "hello module exit\n");   
  15. }   
  16.   
  17. module_init(hello_init);   
  18. module_exit(hello_exit);  

以及对应的Makefile

  1. ifneq ($(KERNELRELEASE),)   
  2. # call from kernel build system   
  3. obj-m   := hello_world.o   
  4. #if we need more than one source code to build the module  
  5. #we should use the variable below:  example: modules-objs := file1.o file2.o  
  6. modules-objs :=   
  7.   
  8. else  
  9. #kernel PTAH   
  10. KERNELDIR ?= /lib/modules/$(shell uname -r)/build   
  11. PWD       := $(shell pwd)   
  12.   
  13. modules:   
  14.     $(MAKE) -C $(KERNELDIR) M=$(PWD) modules   
  15.   
  16. endif   
  17.   
  18. clean:   
  19.     rm -rf *.o *~ core .depend .*.cmd *.ko *.mod.c .tmp_versions  

有几点与用户空间程序不同的地方

  1. 模块程序没有main函数(那么程序入口在哪里?)
  2. 打印函数使用的printk 而不是用户空间的printf 而且使用方式不一样
  3. 模块的编译不是通常的方式
  4. 头文件不是常见的那些头文件
  5. 以及编译之后不会产生可执行文件,而是 .ko 文件
    ...

模块没有main函数,在装载模块 insmod 时会调用module_init注册的函数 此处为hello_init
在模块卸载remod时 会调用module_exit注册的函数 此处为hello_exit
在module_init 注册的函数主要是进行初始化,分配内存, 注册设备等
而module_exit中注册的函数与之相反, 设备注销, 释放内存等
具体的编译模块的Makefile我在另一篇文章中有说到 此处不再赘述
内核的打印函数使用printk去打印信息, printk不支持浮点类型, 在printk中可以加入信息级别有7中

  1. #define KERN_EMERG    "<0>"    /* system is unusable */  
  2. #define KERN_ALERT    "<1>"    /* action must be taken immediately */  
  3. #define KERN_CRIT     "<2>"    /* critical conditions */  
  4. #define KERN_ERR      "<3>"    /* error conditions */  
  5. #define KERN_WARNING  "<4>"    /* warning conditions */  
  6. #define KERN_NOTICE   "<5>"    /* normal but significant */  
  7. #define KERN_INFO     "<6>"    /* informational */  
  8. #define KERN_DEBUG    "<7>"    /* debug-level messages */  
对应与不同的错误等级 选择不懂的option, 并做不同的处理, 小于一定等级的信息会直接打印到终端(非X-window下的终端),可以使用dmesg来查看全部的打印信息
编译内核的头文件是在/lib/modules/$(shell uname -r)/build/include下得,而不是用户模式下得/usr/include
编译后不会生产可执行文件,会生成一个.ko的文件
使用insmod xxx.ko去装载模块
使用lsmod去查看已装载的模块
使用rmmod xxx 去卸载相应模块(卸载是不带.ko)

Linux驱动编程 step-by-step (一)驱动程序的作用

驱动程序的作用: 简单来说 驱动程序就是使计算机与设备通信的特殊的代码,在作单片机时候(无OS)我们自己定义接口及自定义的结构来操作相关硬件,而在有OS的模式下我们操作的硬件是去实现对应的接口(...
  • a8039974
  • a8039974
  • 2014年11月14日 22:45
  • 475

Linux驱动编程 step-by-step (一)

转载于: http://blog.csdn.net/jshazk1989/article/details/6908472 驱动程序的作用: 简单来说 驱动程序就是使计算机与设备通...
  • guoyaoyao1990
  • guoyaoyao1990
  • 2014年07月13日 16:57
  • 346

linux串口驱动——s3c6410平台(一)

1、serial文件夹下Kconfig分析 config SERIAL_SAMSUNG  tristate "Samsung SoC serial support" depends on A...
  • tianxiawuzhei
  • tianxiawuzhei
  • 2012年04月27日 19:56
  • 3765

Linux驱动编程 step-by-step (四)

似乎每一章介绍的内容比较少,但学习是一个循序渐进的过程,不在于一天学多少,重要的一天能真正的学懂多少,所以我主张一步一步来,从多个渠道去学习知识,实现互补。 本节测试代码传到此处了:char_ste...
  • jshazk1989
  • jshazk1989
  • 2011年11月05日 23:48
  • 3307

Linux驱动编程 step-by-step (三)

字符设备中 重要的数据结构 大部分字符驱动设计三个重要的数据结构 struct file_operations struct file struct inode   一、文件操...
  • jshazk1989
  • jshazk1989
  • 2011年11月05日 16:11
  • 3060

Linux驱动编程 step-by-step (五)

主要的文件操作方法实现 文件操作函数有很多的操作接口,驱动编程需要实现这些接口,在用户编程时候系统调用时候会调用到这些操作 struct file_operations { ... loff_...
  • jshazk1989
  • jshazk1989
  • 2011年11月11日 00:35
  • 7723

Linux驱动编程 step-by-step (九)

字符设备模拟pipe的驱动程序 让我们用一个”pipe“的设备驱动去结束简单字符设备吧(这里所说的pipe并非标准的pipe只是模拟了一个从一端写入从另一端写入的设备) 测试代码1      测试...
  • jshazk1989
  • jshazk1989
  • 2011年11月29日 23:17
  • 2859

Linux驱动编程 step-by-step

第三次看了LDD3了(虽然现在已经是kernel3.0但从这本书商还是能学到很多) 每次都有一些收获 现在终于能够写一写代码了 驱动程序的作用: 简单来说 驱动程序就是使计算机与设备通信的特殊的代...
  • Tommy_wxie
  • Tommy_wxie
  • 2012年01月19日 16:55
  • 1565

Linux驱动编程 step-by-step (十一)

Linux 内核链表(2) 之前描述了如何创建内核链表(INIT_LIST_HEAD)向链表中添加节点(list_add)删除一个链表节点(list_del)获取一个链表节点对应的结构体(list_...
  • a8039974
  • a8039974
  • 2014年11月14日 22:50
  • 291

Linux驱动编程 step-by-step (七)

并发 竞态 (信号量与自旋锁) 代码传至并发竞态控制 并发进程 导致竞态的一个例子 前面所述的字符驱动都是没有考虑并发竟态的情况,想象一下 一个进程去读一个字符设备,另一个进程在同...
  • jshazk1989
  • jshazk1989
  • 2011年11月17日 00:24
  • 5726
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:Linux驱动编程 step-by-step (一)驱动程序的作用
举报原因:
原因补充:

(最多只允许输入30个字)