§6.1 设备管理概述
Linux使用套接口(socket)以文件I/O方式提供了对网络数据的访问。
对设备进行初始化
启动或停止设备的运行
把设备上的数据传送到内存
把数据从内存传送到设备
检测设备状态
三.设备的识别
对设备的识别使用设备类型、主设备号、次设备号
设备类型:字符设备还是块设备。
而多个SCSI硬盘及其各个分区分别赋予次设备号1、2、3…。
[root@localhost /]# ls /dev/sda* -l
brw-r----- 1 root disk 8, 0 11-07 12:31 /dev/sda
brw-r----- 1 root disk 8, 1 11-07 12:31 /dev/sda1
brw-r----- 1 root disk 8, 2 11-07 12:31 /dev/sda2
四.设备文件
file_operations结构体得到服务子程序的操作函数入口,然后调用其中的read()函数完成数据输入操作。
分别完成对设备的启动、停止设备运行,向设备输出数据的操作。
§6.2 Linux的I/O控制
Linux的I/O控制方式有三种:查询等待方式、
中断方式和DMA(内存直接存取)方式.
一.查询等待方式
static inline int lp_char_polled(char lpchar, int minor)
{
int status, wait = 0;
unsigned long count = 0;
struct lp_stats *stats;
do { /* 查询等待循环 */
status = LP_S(minor);
count ++;
if(need_resched)
schedule();
} while(!LP_READY(minor,status) && count < LP_CHAR(minor));
if (count == LP_CHAR(minor)) { /* 超时退出 */
return 0;
}
outb_p(lpchar, LP_B(minor)); /* 向设备输出字符 */
.
.
二.中断方式
static struct irqaction *irq_action[NR_IRQS+1];
struct irqaction {
void (*handler)(int, void *, struct pt_regs *); /* 指向中断服务例程 */
unsigned long flags; /* 中断标志 */
unsigned long mask; /* 中断掩码 */
void *dev_id; /*
struct irqaction *next; /* 指向下一个描述符 */
};
的irqaction结构体,并把它登记到irq_action[]数组中。
int request_irq(unsigned int irq,
void (*handler)(int, void *, struct pt_regs *),
unsigned long irqflags,
const char * devname,
void *dev_id);
当
CPU接收到中断请求后,根据中断号就可以通过irq_action[]找到该设备的中断服务例程。
§6.3 字符设备与块设备管理
一.字符设备管理
#define MAX_CHRDEV 128
static struct device_struct chrdevs[MAX_CHRDEV];
struct device_struct {
const char * name; /* 指向设备名字符串 */
struct file_operations * fops; /* 指向文件操作函数的指针 */
};
在
打开一个设备文件时,由主设备号就可以找到设备驱动程序。
二.块设备管理
static struct device_struct blkdevs[MAX_BLKDEV]
struct blk_dev_struct blk_dev[MAX_BLKDEV];
struct blk_dev_struct {
void (*request_fn)(void);
struct request * current_request;
struct request plug;
struct tq_struct plug_tq;
};
request_fn :指向设备读写请求函数的指针
current_request:指向request结构的指针。
当缓冲区需要与设备进行数据交换时,
缓冲机制就在blk_dev_struct中加入一个request结构。
每个request结构对应一个缓冲区对设备的读写请求。
在request结构中有一个指向缓冲区信息的指针,
由它决定缓冲区的位置和大小等