📄 00000002.htm
字号:
<HTML><HEAD> <TITLE>BBS水木清华站∶精华区</TITLE></HEAD><BODY><CENTER><H1>BBS水木清华站∶精华区</H1></CENTER>发信人: dfbb (赵无忌), 信区: Linux <BR>标 题: LINUX下的设备驱动程序 <BR>发信站: BBS 水木清华站 (Sat Dec 13 15:54:36 1997) <BR> <BR> <BR>发信人: olly (剑胆琴心), 信区: Linux <BR>标 题: LINUX下的设备驱动程序 <BR>发信站: BBS 水木清华站 (Sat Jun 28 14:00:08 1997) <BR> <BR> <BR> <BR> 以下是本人毕业论文的一部分,是关于Linux下设备驱动程序的编写的。 <BR>请各位同志们指正。 <BR> <BR> <BR> <BR> <BR> <BR>三、UNIX系统下的设备驱动程序 <BR>3.1、UNIX下设备驱动程序的基本结构 <BR>在UNIX系统里,对用户程序而言,设备驱动程序隐藏了设备的具体细节, <BR>对各种不同设备提供了一致的接口,一般来说是把设备映射为一个特殊的设备文 <BR>件,用户程序可以象对其它文件一样对此设备文件进行操作。UNIX对硬件设备 <BR>支持两个标准接口:块特别设备文件和字符特别设备文件,通过块(字符)特别 <BR>设备文件存取的设备称为块(字符)设备或具有块(字符)设备接口。 <BR>块设备接口仅支持面向块的I/O操作,所有I/O操作都通过在内核地址空间 <BR>中的I/O缓冲区进行,它可以支持几乎任意长度和任意位置上的I/O请求,即提 <BR>供随机存取的功能。 <BR>字符设备接口支持面向字符的I/O操作,它不经过系统的快速缓存,所以它 <BR>们负责管理自己的缓冲区结构。字符设备接口只支持顺序存取的功能,一般不能 <BR>进行任意长度的I/O请求,而是限制I/O请求的长度必须是设备要求的基本块长 <BR>的倍数。显然,本程序所驱动的串行卡只能提供顺序存取的功能,属于是字符设 <BR>备,因此后面的讨论在两种设备有所区别时都只涉及字符型设备接口。 <BR>设备由一个主设备号和一个次设备号标识。主设备号唯一标识了设备类型, <BR>即设备驱动程序类型,它是块设备表或字符设备表中设备表项的索引。次设备号 <BR>仅由设备驱动程序解释,一般用于识别在若干可能的硬件设备中,I/O请求所涉 <BR>及到的那个设备。 <BR>设备驱动程序可以分为三个主要组成部分: <BR>(1) 自动配置和初始化子程序,负责检测所要驱动的硬件设备是否存在和是否 <BR>能正常工作。如果该设备正常,则对这个设备及其相关的、设备驱动程序 <BR>需要的软件状态进行初始化。这部分驱动程序仅在初始化的时候被调用一 <BR>次。 <BR>(2) 服务于I/O请求的子程序,又称为驱动程序的上半部分。调用这部分是由 <BR>于系统调用的结果。这部分程序在执行的时候,系统仍认为是和进行调用 <BR>的进程属于同一个进程,只是由用户态变成了核心态,具有进行此系统调 <BR>用的用户程序的运行环境,因此可以在其中调用sleep()等与进程运行环 <BR>境有关的函数。 <BR>(3) 中断服务子程序,又称为驱动程序的下半部分。在UNIX系统中,并不是 <BR>直接从中断向量表中调用设备驱动程序的中断服务子程序,而是由UNIX <BR>系统来接收硬件中断,再由系统调用中断服务子程序。中断可以产生在任 <BR>何一个进程运行的时候,因此在中断服务程序被调用的时候,不能依赖于 <BR>任何进程的状态,也就不能调用任何与进程运行环境有关的函数。因为设 <BR>备驱动程序一般支持同一类型的若干设备,所以一般在系统调用中断服务 <BR>子程序的时候,都带有一个或多个参数,以唯一标识请求服务的设备。 <BR>在系统内部,I/O设备的存取通过一组固定的入口点来进行,这组入口点是 <BR>由每个设备的设备驱动程序提供的。一般来说,字符型设备驱动程序能够提供如 <BR>下几个入口点: <BR>(1) open入口点。打开设备准备I/O操作。对字符特别设备文件进行打开操 <BR>作,都会调用设备的open入口点。open子程序必须对将要进行的I/O <BR>操作做好必要的准备工作,如清除缓冲区等。如果设备是独占的,即同一 <BR>时刻只能有一个程序访问此设备,则open子程序必须设置一些标志以表 <BR>示设备处于忙状态。 <BR>(2) close入口点。关闭一个设备。当最后一次使用设备终结后,调用close <BR>子程序。独占设备必须标记设备可再次使用。 <BR>(3) read入口点。从设备上读数据。对于有缓冲区的I/O操作,一般是从缓 <BR>冲区里读数据。对字符特别设备文件进行读操作将调用read子程序。 <BR>(4) write入口点。往设备上写数据。对于有缓冲区的I/O操作,一般是把数 <BR>据写入缓冲区里。对字符特别设备文件进行写操作将调用write子程序。 <BR>(5) ioctl入口点。执行读、写之外的操作。 <BR>(6) select入口点。检查设备,看数据是否可读或设备是否可用于写数据。 <BR>select系统调用在检查与设备特别文件相关的文件描述符时使用select入口点。 <BR>如果设备驱动程序没有提供上述入口点中的某一个,系统会用缺省的子程序 <BR>来代替。对于不同的系统,也还有一些其它的入口点。 <BR> <BR>3.2、LINUX系统下的设备驱动程序 <BR>具体到LINUX系统里,设备驱动程序所提供的这组入口点由一个结构来向系 <BR>统进行说明,此结构定义为: <BR>#include <linux/fs.h> <BR>struct file_operations { <BR> int (*lseek)(struct inode *inode,struct file *filp, <BR> off_t off,int pos); <BR> int (*read)(struct inode *inode,struct file *filp, <BR> char *buf, int count); <BR> int (*write)(struct inode *inode,struct file *filp, <BR> char *buf,int count); <BR> int (*readdir)(struct inode *inode,struct file *filp, <BR> struct dirent *dirent,int count); <BR> int (*select)(struct inode *inode,struct file *filp, <BR> int sel_type,select_table *wait); <BR> int (*ioctl) (struct inode *inode,struct file *filp, <BR> unsigned int cmd,unsigned int arg); <BR> int (*mmap) (void); <BR> <BR> int (*open) (struct inode *inode, struct file *filp); <BR> void (*release) (struct inode *inode, struct file *filp); <BR> int (*fsync) (struct inode *inode, struct file *filp); <BR>}; <BR>其中,struct inode提供了关于特别设备文件/dev/driver(假设此设备名 <BR>为driver)的信息,它的定义为: <BR>#include <linux/fs.h> <BR>struct inode { <BR> dev_t i_dev; <BR> unsigned long i_ino; /* Inode number */ <BR> umode_t i_mode; /* Mode of the file */ <BR> nlink_t i_nlink; <BR> uid_t i_uid; <BR> gid_t i_gid; <BR> dev_t i_rdev; /* Device major and minor numbers*/ <BR> off_t i_size; <BR> time_t i_atime; <BR> time_t i_mtime; <BR> time_t i_ctime; <BR> unsigned long i_blksize; <BR> unsigned long i_blocks; <BR> struct inode_operations * i_op; <BR> struct super_block * i_sb; <BR> struct wait_queue * i_wait; <BR> struct file_lock * i_flock; <BR> struct vm_area_struct * i_mmap; <BR> struct inode * i_next, * i_prev; <BR> struct inode * i_hash_next, * i_hash_prev; <BR> struct inode * i_bound_to, * i_bound_by; <BR> unsigned short i_count; <BR> unsigned short i_flags; /* Mount flags (see fs.h) */ <BR> unsigned char i_lock; <BR> unsigned char i_dirt; <BR> unsigned char i_pipe; <BR> unsigned char i_mount; <BR> unsigned char i_seek; <BR> unsigned char i_update; <BR> union { <BR> struct pipe_inode_info pipe_i; <BR> struct minix_inode_info minix_i; <BR> struct ext_inode_info ext_i; <BR> struct msdos_inode_info msdos_i; <BR> struct iso_inode_info isofs_i; <BR> struct nfs_inode_info nfs_i; <BR> } u; <BR>}; <BR> <BR>struct file主要用于与文件系统对应的设备驱动程序使用。当然,其它设 <BR>备驱动程序也可以使用它。它提供关于被打开的文件的信息,定义为: <BR>#include <linux/fs.h> <BR>struct file { <BR> mode_t f_mode; <BR> dev_t f_rdev; /* needed for /dev/tty */ <BR> off_t f_pos; /* Curr. posn in file */ <BR> unsigned short f_flags; /* The flags arg passed to open */ <BR> unsigned short f_count; /* Number of opens on this file */ <BR> unsigned short f_reada; <BR> struct inode *f_inode; /* pointer to the inode struct */ <BR> struct file_operations *f_op;/* pointer to the fops struct*/ <BR>}; <BR> <BR>在结构file_operations里,指出了设备驱动程序所提供的入口点位置,分 <BR>别是: <BR>(1) lseek,移动文件指针的位置,显然只能用于可以随机存取的设备。 <BR>(2) read,进行读操作,参数buf为存放读取结果的缓冲区,count为所要 <BR>读取的数据长度。返回值为负表示读取操作发生错误,否则返回实际读取 <BR>的字节数。对于字符型,要求读取的字节数和返回的实际读取字节数都必 <BR>须是inode->i_blksize的的倍数。 <BR>(3) write,进行写操作,与read类似。 <BR>
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -