阅读内容

Linux驱动程序设计全文详解

[日期:2007-10-19] 来源:Linux公社  作者:Linuxidc


B.初始化和注册和注消,模块方式驱动程序的加载和卸载.

设备驱动程序在定义了数据结构后 ,首先开始初始化:
如I/O 端口的检查和登记,内核对 I/O PORT的检查和登记提供了两个 函数check_region(int io_port, int off_set)
和request_region(int io_port, int off_set,char *devname).I/O Port登记后,就可以用inb()和outb()进行操作了 .

还有DMA和Irq的初始化检查和 登记,
int request_irq(unsigned int irq ,void(*handle)(int,void *,struct pt_regs *),unsigned int long flags,

const char *device);

irq: 是要申请的中断。

handle:中断处理函数指针。

flags:SA_INTERRUPT 请求一个快速中断,0 正常中断。

device:设备名。

如果登记成功,返回0,这时在/proc/interrupts文件中可以看你请求的中断。

DMA主要是在内存中分配交换内存空间.还有缓冲区,设备请求队列的初始化.

还有设备控制寄存器的检查和初始化,还有对设备自身相关的数据结构的初始化,填写一些设备特定的数据等.

然后,开始注册
devfs_register()向VFS注册统一的设备操作函数.
static struct file_operations XXX_fops = {
owner: THIS_MODULE, XXX_fops所属的设备模块
read: XXX_read, 读设备操作
write: XXX_write, 写设备操作
ioctl: XXX_ioctl, 控制设备操作
mmap: XXX_mmap, 内存重映射操作
open: XXX_open, 打开设备操作
release: XXX_release 释放设备操作
/* ... */
};


blk_init_queue()队列初始化函数.
request_irq()中断注册函数
相应的注消函数:
devfs_unregister (devfs_handle_t de){};
free_irq()释放中断,I/O资源,释放缓冲区,释放设备,请求队列,VFS节点等.

模块方式驱动程序的加载和卸载.

static int __init _init_module (void)
{
/* ... */
}

static void __exit _cleanup_module (void)
{

}

/* 加载驱动程序模块入口 */
module_init(_init_module);

/* 卸载驱动程序模块入口 */
module_exit(_cleanup_module);


_intrrupt()
设备发生中断时的处理程序.
{
1.对共享中断的处理;
2.对spinlock以及其他的事务的处理;
}

C. 底层设备操作函数的编写
read().write(),open(),release(),check_media_change(),revalidate()等.


open()和release()

打开设备是通过调用file_operations结构中的函数open( )来完成的,它是驱动程序用来为今后的操作完成初始化准备工作的。在大部分驱动程序中,open( )通常需要完成下列工作:

1. 检查设备相关错误,如设备尚未准备好等。
2. 如果是第一次打开,则初始化硬件设备。
3. 识别次设备号,如果有必要则更新读写操作的当前位置指针f_ops。
4. 分配和填写要放在file->private_data里的数据结构。
5. 使用计数增1。

释放设备是通过调用file_operations结构中的函数release( )来完成的,这个设备方法有时也被称为close( ),它的作用正好与open( )相反,通常要完成下列工作:

1. 使用计数减1。
2. 释放在file->private_data中分配的内存。
3. 如果使用计算为0,则关闭设备。

read()和 write()

字符设备的读写操作相对比较简单,直接使用函数read( )和write( )就可以了。但如果是块设备的话,则需要调用函数block_read( )和block_write( )来进行数据读写,这两个函数将向设备请求表中增加读写请求,以便Linux内核可以对请求顺序进行优化。由于是对内存缓冲区而不是直接对设备进行操作的,因此能很大程度上加快读写速度。如果内存缓冲区中没有所要读入的数据,或者需要执行写操作将数据写入设备,那么就要执行真正的数据传输,这是通过调用数据结构blk_dev_struct中的函数request_fn( )来完成的。

ioctl()--将cmd进行解释,并送到设备的控制寄存器.事实上,read()和write()也要通过ioctl()来完成操作的 .
ioctl(){
CASE CMD{
SWITCH CASE1:{...};
SWITCH CASE2:{...};
SWITCH CASE N:{...};
.
.
DEFAULT : {...};
}
END CASE
总结:
我们可以看出一个linux的驱动程序通常包含如下:
初始化设备模块、
{I/O port ,DMA.Irq,内存 buffer,初始化并且填写具体设备数据结构,注册 fops的具体函数等等 }
中断处理模块、设备释放模块、设备卸载模块
设备打开模块、数据读写和控制模块、
驱动装载模块、驱动释放模块.

浙江省城乡规划设计研究院计算机中心
陈刚 2004.07.21

上一页12  GO
【内容导航】
第1页:Linux驱动程序设计全文详解 第2页:Linux驱动程序设计全文详解



相关资讯       Linux驱动 
本文评论       全部评论
发表评论
  • 尊重网上道德,遵守中华人民共和国的各项有关法律法规
  • 承担一切因您的行为而直接或间接导致的民事或刑事法律责任
  • 本站管理人员有权保留或删除其管辖留言中的任意内容
  • 本站有权在网站内转载或引用您的评论
  • 参与本评论即表明您已经阅读并接受上述条款


点评: 字数
姓名:

L
I
N
U
X


GOOGLE搜索
Google