2011-7-10 14:56:05

 

 

 

2011-7-10 14:56:05

 


设备驱动使用内存

与核心的其它部分一样,设备驱动不依赖于任何运行的特定进程。设备驱动使用数据结构来描述它所控制的设备。这些结构被设备驱动代码以静态方式分配,

这会增大核心而引起空间的浪费。多数设备驱动使用核心中非页面内存来存储数据。

Linux为设备驱动提供了一组核心内存分配与回收过程。核心内存以2的次幂大小的块来分配。如512或128字节,此时即使设备驱动的需求小于这个数量也会分配这么多。

所以设备驱动的内存分配请求可得到以块大小为边界的内存。这样核心进行空闲块组合更加容易。

请求分配核心内存时Linux需要完成许多额外的工作。如果系统中空闲内存数量较少,则可能需要丢弃些物理页面或将其写入交换设备。一般情况下Linux将挂起请求者

并将此进程放置到等待队列中直到系统中有足够的物理内存为止。


设备文件及接口
Linux所有的设备都被看成文件,通过文件操作的界面进行操作。每一项设备都至少由文件系统中的一个文件(或者说是节点)代表,

应用程序通过设备的文件名寻访具体的设备,而设备则像普通文件一样受到文件系统访问权限控制机制的保护。应用程序通过系统调用open()"打开"设备文件,

建立起与目标设备的连接。代表着该设备的文件节点中记载着建立这种连接所需的信息。对于执行该应用程序的进程而言,建立起的连接就表现为一个已打开文件。

打开了设备文件,即建立起与设备的连接以后,就可以通过read()、write()、ioctl()等常规的文件操作对目标设备进行操作。从应用程序的角度看,设备文件逻辑上

的空间是个线性空间。从这个逻辑空间到具体设备的物理空间的映射则由内核提供,并划分成文件操作与设备驱动两个层次。

即插即用
即插即用就是对没配置的设备进行检测并设置资源。linux即插即用层给相应的驱动程序提供了下面这些服务:

id 显示支持ELSA ID的链表

options 显示可能的资源配置

resources 显示当前分配的资源和允许的资源变化。

用下述shell命令触发自动的资源配置系统来示激活一个设备:

#echo  “auto” > resource

资源配置系统来激活一个设备

用下述shell命令手动激活一个设备:

#echo "manual <depnum> <mode>" > resources
<depnum>  表示配置号
<mode>   表示是静态的学是动态的。
  static = 下一次启动起作用
  dynamic = 现在起作用

用下述shell命令使资源失效:

#echo "disable" > resources


例如:激活软驱控制器。

切换到相应目录:

# cd /driver/bus/pnp/devices/00:0f
# cat name
PC standard floppy disk controller

用下述shell命令检查设备是否已激活:

# cat resources
DISABLED

它表示设备还没被激活。

用下述shell命令检查设备的可选的配置:

# cat options
Dependent: 01 - Priority acceptable
    port 0x3f0-0x3f0, align 0x7, size 0x6, 16-bit address decoding
    port 0x3f7-0x3f7, align 0x0, size 0x1, 16-bit address decoding
    irq 6
    dma 2 8-bit compatible
Dependent: 02 - Priority acceptable
    port 0x370-0x370, align 0x7, size 0x6, 16-bit address decoding
    port 0x377-0x377, align 0x0, size 0x1, 16-bit address decoding
    irq 6
dma 2 8-bit compatible

用下述shell命令触发自动的资源配置系统来示激活一个设备:

# echo "auto" > resources最后用下述shell命令检查设备是否激活:

# cat resources
io 0x3f0-0x3f5
io 0x3f7-0x3f7
irq 6
dma 2

激活软驱

(2)统一的PnP层
linux在设备驱动之上建立了统一的PnP层,所有的即插即用驱动程序、协议和服务在称为PnP层的上面相会,

pnp层负责在PnP驱动程序和PnP协议之间信息交换。pnp层自动地向前传递命令给合适的协议。这使得写PnP驱动程序更容易。从PnP层有下面这些函数可以使用:

pnp_get_protocol 增加使用计数

pnp_put_protocol 减小使用计数

pnp_register_protocol 注册新的PnP协议

pnp_unregister_protocol 从PnP层移去协议

pnp_register_driver 在PnP层注册PnP驱动程序

pnp_unregister_driver 在PnP层注销PnP驱动程序

 

(3)PnP协议
下面的协议是当前可用的:

- PNPBIOS协议: 它被诸如串口和并口这样的系统设备使用。

- ISAPNP协议: 它支持ISA总线的PnP。

- ACPI协议: PnP是ACPI协议众多使用中的一种,提供关于系统级的设备信息。它将代替PNPBIOS协议.

PnP协议的管理结构是pnp_protocol,列出如下(在include/linux/pnp.h中):

struct pnp_protocol {
 struct list_head protocol_list;
 char        * name;
 
 //资源控制函数
 int (*get)(struct pnp_dev *dev, struct pnp_resource_table *res);
 int (*set)(struct pnp_dev *dev, struct pnp_resource_table *res);
 int (*disable)(struct pnp_dev *dev);
 
 //仅被pnp层使用的成员
 unsigned char  number;  //协议数
 struct device  dev;  //链接到驱动程序模型
 struct list_head cards;
 struct list_head devices;
};

在drivers/pnp/core.c声明了与pnp相关的全局链表,列出如下:

LIST_HEAD(pnp_protocols);//pnp协议结构的全局链表
LIST_HEAD(pnp_global); //pnp设备的全局链表

下面是PnP协议管理相关的函数说明(在drivers/pnp/core.c中):

函数pnp_add_device 使用这个函数加一个PnP设备到PnP层,仅在所有所需的值都被设在结构pnp_dev中时才调用这个函数。

函数pnp_init_device 调用这个函数来初始化PnP结构。

函数pnp_remove_device 调用这个函数从PnP层移去一个设备,如果设备还在使用,它将失败。这个函数将自动释放设备相关的内存和相关结构。

函数pnp_add_id 加一个EISA ID到特定设备支持的ID链表中。

你可能感兴趣的:(linux,list,struct,shell,resources,protocols)