一、认识驱动
1、什么是驱动
不知道的情况下,我们一般会去问度娘,但是度娘的这个回答比较专业化,对小白来说并不容易理解,依旧不明白驱动到底是个啥。 度娘:驱动,计算机软件术语,是指驱动计算机里软件的程序。驱动程序全称设备驱动程序,是添加到操作系统中的特殊程序,其中包含有关硬件设备的信息。此信息能够使计算机与相应的设备进行通信。驱动程序是硬件厂商根据操作系统编写的配置文件,可以说没有驱动程序,计算机中的硬件就无法工作。
俺的理解:驱动,字面意思:想要某种东西动起来、运作起来,就得给它施加外力。比如风车能动起来,受到了风力,洗衣机要运作,得给它供电(电力),因此我们的硬件要运作起来就需要用代码去操纵、驱动它,而这段代码就叫硬件的驱动程序。因此狭义上,驱动程序专指操作系统中的用来操控硬件系统的代码。
2、驱动的作用
驱动的主要作用是计算机系统与硬件设备之间完成数据传送的功能,只有借助驱动程序,两者才能通信并完成特定的功能。如果一个硬件设备没有驱动程序,只有操作系统是不能发挥特有功效的,也就是说驱动程序是介于操作系统与硬件之间的媒介,实现双向的传达,即将硬件设备本身具有的功能传达给操作系统,同时也将操作系统的标准指令传达给硬件设备,从而实现两者的无缝连接。
3、驱动的分层思想
驱动的上层是API(即应用程序调用API,API调用驱动),驱动的下层是硬件(硬件抽象为寄存器)。
二、Linux设备驱动分类
根据设备读写操作特征差异的原则,分为以下三类:
(1)字符设备驱动
字符设备,准确的说应该叫“字节设备”,软件操作设备时是以字节为单位进行的。典型的如LCD、串口(一个一个字节的去读或者去发送)、LED(读写寄存器也是以字节为单位操作的)、蜂鸣器、触摸屏等等。
(2)块设备驱动
块设备,块设备是相对于字符设备定义的,块设备被软件操作时是以块(多个字节构成的一个单位)为单位的。设备的块大小是设备本身设计时定义好的,软件是不能去更改的,不同设备的块大小可以不一样。常见的块设备都是存储类设备,如:硬盘、NandFlash、iNand、SD等,想将某个字节的a改成b,必须将整个块读取到内存中,找到这个字节,将这个字节修改(在内存中可以以字节为单位访问),然后将整个块的内容再写入到块设备中。
(3)网络设备驱动
网络设备,网络设备是专为网卡设计的驱动模型,linux中网络设备驱动主要目的是为了支持API中socket相关的函数工作。
其中字符设备驱动最重要,因为常见大量设备都属于字符设备。
三、驱动与内核的关系
1、驱动是内核最庞大的组成部分,内核会直接以函数调用的方式调用驱动代码,驱动的动态安装和卸载都会“更改”内核。
2、驱动程序崩溃甚至会导致内核崩溃,驱动的效率会影响内核的整体效率(以字节为单位读写还是以块为单位读写),驱动的漏洞会造成内核安全漏洞。
四、常见驱动安全性问题
(1)未初始化指针,非法访问;
(2)恶意用户程序;
(3)缓冲区溢出,应用传给驱动的参数过多,覆盖掉有用的数 据; (4)竞争状态(自旋锁,互斥锁)。
五、mmap技术
1、拷贝读写文件
传统的修改文件一般要经过:把文件内容读入内存中;修改内存中的内容;把内存中的数据写入到文件中。这时读写文件的中间层叫页缓存,内核使用页缓存将文件的数据块关联起来,应用程序读写文件时,实际操作的是页缓存。那么如何才能免去将页缓存的数据复制到用户空间缓冲区的过程,直接在用户空间读写页缓存呢?
答案就是mmap技术!
2、认识mmap
mmap:零拷贝技术的一种体现,简单来说就是mmap是直接将进程的虚拟地址和内核空间的page cache进行映射从而省去了从内核空间向用户空间的copy。
(1)使用 mmap系统调用可以将用户空间的虚拟内存地址与文件进行映射(绑定),对映射后的虚拟内存地址进行读写操作就如同对文件进行读写操作一样。
(2)mmap映射的是文件的页缓存,而非磁盘中的文件本身。
(3)使用 mmap 对文件进行读写操作时可以减少内存拷贝的次数,并且可以减少系统调用的次数,从而提高对读写文件操作的效率。
(4)Linux 内核并不会主动把 mmap 映射的页缓存同步到磁盘,而是需要用户主动触发。同步 mmap 映射的内存到磁盘有 4 个时机:
调用 msyns函数主动进行数据同步(主动);
调用 munmap函数对文件进行解除映射关系时(主动);
进程退出时(被动);
系统关机时(被动)。
由于内核不会主动同步 mmap所映射的内存区中的数据,所以在某些特殊的场景下可能会出现数据丢失的情况(如断电)。为了避免数据丢失,在使用 mmap的时候可以在适当时主动调用 msync函数来同步映射内存区的数据。
3、mmap函数
函数原型:
void *mmap(void *addr, size_t length, int prot, int flags, int fd, off_t offset);
各参数的作用:
addr:指定映射的虚拟内存地址,可以设置为 NULL,让 Linux 内核自动选择合适的虚拟内存地址。
length:映射的长度。
prot:映射内存的保护模式,可选值如下:
PROT_EXEC:可以被执行。
PROT_READ:可以被读取。
PROT_WRITE:可以被写入。
PROT_NONE:不可访问。
flags:指定映射的类型,常用的可选值如下:
MAP_FIXED:使用指定的起始虚拟内存地址进行映射。
MAP_SHARED:与其它所有映射到这个文件的进程共享映射空间(可实现共享内存)。
MAP_PRIVATE:建立一个写时复制(Copy on Write)的私有映射空间。
MAP_LOCKED:锁定映射区的页面,从而防止页面被交换出内存。
...
fd:进行映射的文件句柄。
offset:文件偏移量(从文件的何处开始映射)。
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)