linux设备驱动

Linux系统把设备驱动分成字符设备、块设备和网络设备三种类型。

内核为设备驱动提供了注册和管理的接口,设备驱动还可以使用内核提供的其他功能以及访问内核资源。


PCI局部总线

早期的计算机有众多总线标准。从最初的8位总线到16位总线,到目前主流的32位总线,不同厂商都制定了自己的总线标准。不同的总线设备给设备驱动的设计带了麻烦,直到后来PCI局部总线出台这种局面才得到缓解,并且逐步成为事实上的标准。

PCI是英文Peripheral Component Interconnect的缩写,中文意思是外设部件互连标准。

PCI局部总线标准最早由英特尔公司为制定,最初主要应用在PC机。目前已经被越来越多的嵌入式系统已经其他类型的计算机系统使用。

设计PCI的原因是由于之前的总线有许多的缺点,归纳总结为以下几点:

    • 总线速度过慢。

    • 总线地址分配方法复杂。

    • 总线资源共享效率低。

PCI总线采用软件配置地址和其它总线信息的方法,避免了手工配置设备在总线地址带来的麻烦,此外,PCI还支持通过桥的方式扩展总线的处理能力。


Linux设备驱动基本概念

在Linux系统中,所有的资源都是作为文件管理的,设备驱动也不例外,设备驱动通常是作为一类特殊的文件存放在/dev目录下。

total 0
crw------- 1 root root 10, 58 Jun 8 11:40 alarm
crw------- 1 root root 10, 59 Jun 8 11:40 ashmem
crw------T 1 root root 10, 235 Jun 8 11:40 autofs
crw------- 1 root root 10, 60 Jun 8 11:40 binder
drwxr-xr-x 2 root root 740 Jun 8 2013 block
drwxr-xr-x 2 root root 80 Jun 8 2013 bsg
crw------T 1 root root 10, 234 Jun 8 11:40 btrfs-control
drwxr-xr-x 3 root root 60 Jun 8 2013 bus
lrwxrwxrwx 1 root root 3 Jun 8 11:40 cdrom -> sr0
lrwxrwxrwx 1 root root 3 Jun 8 11:40 cdrw -> sr0
drwxr-xr-x 2 root root 3700 Jun 8 11:40 char
crw------- 1 root root 5, 1 Jun 8 11:40 console
lrwxrwxrwx 1 root root 11 Jun 8 11:40 core -> /proc/kcore
drwxr-xr-x 2 root root 60 Jun 8 11:40 cpu
crw------- 1 root root 10, 57 Jun 8 11:40 cpu_dma_latency
drwxr-xr-x 6 root root 120 Jun 8 2013 disk

这里仅列出了一部分文件,设备文件属性最开始的一个字符c表示该设备文件关联的是一个字符设备;b表示关联的是一个块设备。在文件列表的中间部分有两个数字,第一个数字称做主设备号,第二个数字称做次设备号。

在内核中使用主设备号标识一个设备,次设备号提供给设备驱动使用。

在打工一个设备的时候,内核会根据设备的主设备号得到设备驱动,并且把次设备传递给驱动。linux内核为所有设备都分配了主设备号,在编写驱动程序之前需要参考内核代码Documentation/devices.txt文件,确保使用的设备号没有被占用。

在使用一个设备之前,需要使用linux提供的mknod命令建立设备文件。mknod命令格式如下

mknod [OPTION] ... NAME TYPE [MAJOR MINOR]

其中,NAME是设备文件名称;TYPE是设备类型,c代码字符设备,b代表块设备;MAJOR是主设备号,MINOR是次设备号。OPTION是选项,-m参数用于指定设备文件访问权限。

linux内核按照外部设备工作特点把设备分成了字符设备、块设备和网络设备3种基本类型。

在编写设备驱动的时候,需要使用内核提供的设备驱动接口,向内核提供具体设备的操作方法。


字符设备

字符设备是Linux系统最简单的一类设备。

应用程序可以像操作普通文件一样操作字符设备。常见的串口、调制解调器都是字符设备。

编写字符设备驱动需要使用内核提供的register_chardev()函数注册一个字符设备驱动。

函数定义如下:

int register_chrdev(unsigned int major, const char *name, struct file_operations *fops);

fops是指向函数指针数组的结构指针,驱动程序的入口函数都包括在这个指针内部。

该函数的返回值如果小于0表示注册设备驱动失败,如果设置major为0,表示由内核动态分配主设备号,函数的返回值是主设备号。

当使用register_chardve()函数成功注册一个字符设备后,会在/proc/devices文件中显示出设备信息

mystery@lcw:~$ cat /proc/devices
Character devices:
1 mem
4 /dev/vc/0
4 tty
4 ttyS
7 vcs
10 misc
13 input
21 sg
29 fb
99 ppdev
108 ppp
253 watchdog
254 rtc
Block devices:
1 ramdisk
259 blkext
7 loop
8 sd
9 md
252 device-mapper
253 virtblk
254 mdp

删除了一些,其中Character devices是字符设备驱动列表,Block devices是块设备驱动列表,数字代表主设备驱动,后面是设备驱动名称。

与注册驱动相反,内核提供了unregister_chardev()函数卸载设备驱动or

int unregister_chrdev(unsigned int major, const char *name);

内核会比较设备驱动名称与设备号是否相同,如果不同函数返回-EINVAL。错误地卸载设备驱动会带来严重后果,因此在卸载驱动的时候应该对函数返回值做判断。

在register_chardev()函数中有一个fops参数,该参数指向一个file_operation结构,该结构包含了驱动上的所有操作。随着内核功能的不断增加,file_operations结构的定义也越来越复杂。

大部分驱动都没有提供所有的函数,对于字符设备来说,常用的函数如下


块设备

与字符设备相比,块设备要复杂的多。

最主要的差别是块设备带有缓冲,字符设备没有。

块设备传输数据只能以块作为单位读写,字符设备是以字节作为最小读写单位的。块设备对于I/O请求有对应的缓冲区,可以选择响应的顺序,如采用特定的调度策略等;字符设备只能顺序访问。

此外,块设备提供了随机访问的能力,而字符设备之顺序读取数据。

块设备提供了一个类似字符设备的访问函数结构block_device_operations,定义如下

struct block_device_operations
{
int (*open) (struct inode *, struct file *);
int (*release) (struct inode *, struct file *);
int (*ioctl) (struct inode *, struct file *, unsigned, unsigned long);
long (*unlocked_ioctl) (struct file *, unsigned, unsigned long);
long (*compat_ioctl) (struct file *, unsigned, unsigned long);
int (*direct_access) (struct block_device *, sector_t, unsigned long *);
int (*media_changed) (struct gendisk *);
int (*revalidate_disk) (struct gendisk *);
int (*getgeo)(struct block_device *, struct hd_geometry *);
struct module *owner;
};

其中,open、release、ioctl等函数的功能与字符设备相同。

块设备提供了几个特有的函数成员:

    • media_change()函数用来检查介质是否改变,主要用于检查可移动设备;

    • revalidate_disk()函数响应物理介质的改变请求;

    • getgen()函数用于向系统汇报驱动器信息。


网络设备

在Linux内核中,网络设备是一类特殊的设备,因此被单独设计为一种类型的驱动。

与其他设备不同的是,网络设备不是通过设备文件访问的,在/dev目录下不会看到任何网络设备。因此,网络设备的操作不是通过文件操作实现的。

Linux内核为了抽象网络设备界面,为其定义了一个接口用于屏蔽网络环境下各种网络设备的差别。内核对所有网络设备的访问都通过这个抽象的接口,接口对上层网络协议提供相同的操作方法。

本文出自 “成鹏致远” 博客,请务必保留此出处http://infohacker.blog.51cto.com/6751239/1218747

【驱动】linux设备驱动·扫盲的更多相关文章

  1. linux设备驱动归纳总结

    前言: (总结已经基本写完,这段时间我会从新排版和修正.错误总会有的,望能指正!) 前段时间学习了嵌入式驱动,趁着没开始找工作,这段时间我会每天抽出时间来复习. 我的总结是根据学习时的笔记(李杨老师授 ...

  2. 【Linux】linux设备驱动归纳总结

    前言: (总结已经基本写完,这段时间我会从新排版和修正.错误总会有的,望能指正!) 前段时间学习了嵌入式驱动,趁着没开始找工作,这段时间我会每天抽出时间来复习. 我的总结是根据学习时的笔记(李杨老师授 ...

  3. 字符设备驱动、平台设备驱动、设备驱动模型、sysfs的比较和关联

    转载自:http://www.kancloud.cn/yueqian_scut/emlinux/106829 学习Linux设备驱动开发的过程中自然会遇到字符设备驱动.平台设备驱动.设备驱动模型和sy ...

  4. [kernel]字符设备驱动、平台设备驱动、设备驱动模型、sysfs几者之间的比较和关联

    转自:http://www.2cto.com/kf/201510/444943.html Linux驱动开发经验总结,绝对干货! 学习Linux设备驱动开发的过程中自然会遇到字符设备驱动.平台设备驱动 ...

  5. 【驱动】linux设备驱动·字符设备驱动开发

    Preface 前面对linux设备驱动的相应知识点进行了总结,现在进入实践阶段! <linux设备驱动入门篇>:http://infohacker.blog.51cto.com/6751 ...

  6. 浅谈Android系统移植、Linux设备驱动

    一.Android系统架构 第一层:Linux内核 包括驱动程序,管理内存.进程.电源等资源的程序 第二层:C/C++代码库 包括Linux的.so文件以及嵌入到APK程序中的NDK代码 第三层:An ...

  7. linux设备驱动概述,王明学learn

    linux设备驱动学习-1 本章节主要学习有操作系统的设备驱动和无操作系统设备驱动的区别,以及对操作系统和设备驱动关系的认识. 一.设备驱动的作用 对设备驱动最通俗的解释就是“驱使硬件设备行动” .设 ...

  8. Linux设备驱动工程师之路——内核链表的使用【转】

    本文转载自:http://blog.csdn.net/forever_key/article/details/6798685 Linux设备驱动工程师之路——内核链表的使用 K-Style 转载请注明 ...

  9. linux设备驱动归纳总结(十三):1.触摸屏与ADC时钟【转】

    本文转载自:http://blog.chinaunix.net/uid-25014876-id-119723.html linux设备驱动归纳总结(十三):1.触摸屏与ADC时钟 xxxxxxxxxx ...

随机推荐

  1. 抗衡Win Linux全凭这些桌面环境

    2012年01月25日 元老级桌面环境KDE     Linux操作系统最早使用在服务器上,而桌面操作系统并不是Linux的重点突围.但是,近几年Linux桌面操作系统有崛起的趋势,抢夺了部分桌面操作 ...

  2. linux shell 脚本攻略学习15--如何只列出目录,如何快速切换目录

    工作中经常遇到关于目录方面的问题,例如,如何只列出当前目录下的所有目录,以及如何快速高效的切换目录,而不需要使用鼠标,下面将简单介绍关于这两方面的解决方案: 一.如何只列出目录? 看似简单的任务,其实 ...

  3. 工作8年对技术学习过程的一些 总结 与 感悟 为什么有时迷茫、无奈 学习编程语言的最高境界最重要的是编程思想 T 字发展 学技术忌讳”什么都会“ 每天进步一点等式图 时间管理矩阵

    工作这些年对技术学习过程的一些 总结 与 感悟(一) 引言 工作了8年,一路走来总有些感触时不时的浮现在脑海中.写下来留个痕迹,也顺便给大家一点参考.希望能给初学者一点帮助. 入门 进入计算机行业,起 ...

  4. 安装samba脚本

    Ubuntu_samba.sh #!/bin/sh echo "Ubuntu 14.04 文件服务器--samba的安装和配置" echo "更新源列表" su ...

  5. ios面试题来一波

    一.如果让你实现属性的weak,如何实现的? PS: @property 等同于在.h文件中声明实例变量的get/set方法, 而其中property有一些关键字,其中就包括weak,atomic的. ...

  6. redis常用性能分析命令

    一.连接 src/redis-cli -h 10.20.137.141 -p 6379 >auth 123456789 src/redis-cli -h 10.20.137.141 -p 637 ...

  7. thinkphp __hash__

    thinkphp会自动在模板文件的表单后加一个__hash__来验证提交,保证一定程序上的安全: 但是有时用不着,可以用: C('TOKEN_ON',false); 关闭这项

  8. tp数据库表大写命名的一些问题

    在使用thinkphp时,如果数据库表命名有大写,会被转换成小写加下划线(可以使用$model->_sql())来查看实际执行的sql是什么 这个问题,看了一下源代码,在 Thinkphp/Co ...

  9. Office 2010 安装程序包的语言不受系统支持

    主要看了这篇文章之后让我有了处理思路. 最后我直接用压缩文件进行安装,没有时行解压.这样就不会出现找不到什么文件的问题了.所以语言不受系统支持问题也就解决了. 原文内容: 前几天,有位好友跟我说他的 ...

  10. Jmeter录制HTTPS

    Jmeter有录制功能,录制HTTPs需要增加一个证书配置,录制步骤如下: 1.打开jmeter,添加线程组.线程组右键,逻辑控制器>录制控制器 工作台 右键 非测试元件 >HTTP代理服 ...