新闻中心

EEPW首页 > 嵌入式系统 > 设计应用 > linux 基础复习(9)设备驱动入门

linux 基础复习(9)设备驱动入门

作者:时间:2016-10-08来源:网络收藏

Linux 内核中采用可加载的模块化设计(LKMs,Loadable Kernel Modules),一般情况下编译的Linux 内核是支持可插入式模块的,也就是将最基本的核心代码编译在内核中,其他的代码可以选择在内核中,或者编译为内核的模块文件。常见的驱动程序也是作为内核模块动态加载的。

本文引用地址:http://www.eepw.com.cn/article/201610/305814.htm

模块相关命令

lsmod 列出当前系统加载的模块

rmmod 将当前模块卸载

insmod、modprobe 用于加载当前模块。但insmod不会自动解决依存关系,而modprobe可以根据模块间的依存关系以及 /etc/modules.conf 文件中的内容自动插入模块

mknod 创建相关模块

Linux 系统的设备文件分为三类:块设备文件、字符设备文件和网络设备文件。

· 块设备文件通常指一些需要以块(如512 字节)的方式写入的设备,如IDE 硬盘、SCSI硬盘、光驱等。

· 字符型设备文件通常指可以直接读写,没有缓冲区的设备,如并口、虚拟控制台等。

· 网络设备文件通常是指网络设备访问的BSD socket接口,如网卡等。

设备号设备号是一个数字,它是设备的标志。就如前面所述,一个设备文件(也就是设备节点)可以通过mknod命令来创建,其中指定了主设备号和次设备号。主设备号表明某一类设备,

一般对应着确定的驱动程序;次设备号一般是用于区分标明不同属性,例如不同的使用方法,不同的位置,不同的操作等,它标志着某个具体的物理设备。高字节为主设备号和底字节为次设备号。例如,在系统中的块设备IDE 硬盘的主设备号是3,而多个IDE 硬盘及其各个分区分别赋予次设备号1、2、3……

Linux 设备驱动程序包含中断处理程序和设备服务子程序两部分

设备服务子程序包含了所有与设备操作相关的处理代码。它从面向用户进程的设备文件系统中接受用户命令,并对设备控制器执行操作。这样,设备驱动程序屏蔽了设备的特殊性,使用户可以像对待文件一样操作设备。

设备控制器需要获得系统服务时有两种方式:查询和中断。因为Linux 下的设备驱动程序是内核的一部分,在设备查询期间系统不能运行其他代码,查询方式的工作效率比较低,所以只有少数设备如软盘驱动程序采取这种方式,大多设备以中断方式向设备驱动程序发出输入/输出请求。

screen.width*0.7) {this.resized=true; this.width=screen.width*0.7; this.style.cursor='hand'; this.alt='Click here to open new windownCTRL+Mouse wheel to zoom in/out';} onclick=if(!this.resized) {return true;} else {window.open(this.src);} alt= src=http://blogimg.chinaunix.net/blog/upfile2/080413193842.jpg onload=if(this.width>screen.width*0.7) {this.resized=true; this.width=screen.width*0.7; this.alt='Click here to open new windownCTRL+Mouse wheel to zoom in/out';} border=0>

Linux 中的设备驱动程序有如下特点。

(1)内核代码:设备驱动程序是内核的一部分,如果驱动程序出错,则可能导致系统崩溃。

(2)内核接口:设备驱动程序必须为内核或者其子系统提供一个标准接口。比如,一个终端驱动程序必须为内核提供一个文件I/O 接口;一个SCSI设备驱动程序应该为SCSI子系统提供一个SCSI设备接口,同时SCSI子系统也必须为内核提供文件的I/O 接口及缓冲区。

(3)内核机制和服务:设备驱动程序使用一些标准的内核服务,如内存分配等。

(4)可装载:大多数的Linux 操作系统设备驱动程序都可以在需要时装载进内核,在不需要时从内核中卸载。

(5)可设置:Linux 操作系统设备驱动程序可以集成为内核的一部分,并可以根据需要把其中的某一部分集成到内核中,这只需要在系统编译时进行相应的设置即可。

(6)动态性:在系统启动且各个设备驱动程序初始化后,驱动程序将维护其控制的设备。

如果该设备驱动程序控制的设备不存在也不影响系统的运行,那么此时的设备驱动程序只是多占用了一点系统内存罢了。

驱动开发时却没有main 函数,模块在调用insmod命令时被加载,此时的入口点是init_module函数,通常在该函数中完成设备的注册。同样,模块在调rmmod

函数时被卸载,此时的入口点是cleanup_module函数,在该函数中完成设备的卸载。在设备完成注册加载之后,用户的应用程序就可以对该设备进行一定的操作,如read、write等,而驱动程序就是用于实现这些操作,在用户应用程序调用相应入口函数时执行相关的操作,init_module入口点函数则不需要完成其他如read、write之类功能。

设备驱动程序的入口点,它是一个在中定义的struct file结构,这是一个内核结构,不会出现在用户空间的程序中,它定义了常见文件I/O 函数的入口。

struct file_operations {

loff_t (*llseek) (struct file *, loff_t, int);

ssize_t (*read) (struct file *filp, char *buff, size_t count, loff_t *offp);

ssize_t (*write) (struct file *filp, const char *buff, size_t count, loff_t *offp);

int (*readdir) (struct file *, void *, filldir_t);

unsigned int (*poll) (struct file *, struct poll_table_struct *);

int (*ioctl) (struct inode *, struct file *, unsigned int, unsigned

long);

int (*mmap) (struct file *, struct vm_area_struct *);

int (*open) (struct inode *, struct file *);

int (*flush) (struct file *);

int (*release) (struct inode *, struct file *);

int (*fsync) (struct file *, struct dentry *);

int (*fasync) (int, struct file *, int);

int (*check_media_change) (kdev_t dev);

int (*revalidate) (kdev_t dev);

int (*lock) (struct file *, int, struct file_lock *);

};

每个设备的驱动程序不一定要实现其中所有的函数操作,若不需要定义实现时,则只需将其设为NULL即可。


上一页 1 2 3 下一页

关键词:

评论


相关推荐

技术专区

关闭