分类: LINUX
2010-04-27 20:46:24
1.字符设备与块设备IO操做的区别
1)块设备只能以块为单位接收输入返回输出,而字符设备则以byte为单位.大多数设备是字符设备,他们不需要缓冲并且不以固定块大小进行操作.
2)块设备对于IO请求有对应的缓冲区,所以他们可以选择以什么顺序进行响应.字符设备无须缓冲且被直接读写.
3)字符设备只能被顺序读写,块设备可以随机访问.
2.block_device_operations结构体
block_device_operations描述了对块设备的操作的集合
struct block_device_operations {
int (*open) (struct inode *, struct file *);/*打开*/
int (*release) (struct inode *, struct file *);/*释放*/
int (*ioctl) (struct inode *, struct file *, unsigned, unsigned long);
long (*unlocked_ioctl) (struct file *, unsigned, unsigned long);
long (*compat_ioctl) (struct file *, unsigned, unsigned long);
int (*direct_access) (struct block_device *, sector_t, unsigned long *);
int (*media_changed) (struct gendisk *);/*介质被改变?*/
int (*revalidate_disk) (struct gendisk *);/*使介质改变*/
int (*getgeo)(struct block_device *, struct hd_geometry *);/*填充驱动器信息*/
struct module *owner;/*模块拥有者,一般初始化为THIS_MODULE*/
};
关于block_device_operations的操作:
//open and release
int (* open)(struct inode*, struct file*);
int (* release)(struct inode*, struct file*);
//io contrl
//系统调用实现,块设备包含大量的标准请求,由设备层处理,所以此函数一般相当短
int (* ioctl)(struct inode*,struct file*,unsigned int,unsigned long);
//media changed
//如果改变返回非0值,否则返回0
int (*media_changed)(struct gendisk*);
//revalidate media
//用于相应一个介质的改变,给驱动一个机会做准备工作
int (* revalidate_disk)(struct gendisk*);
//get driver informaiton
//根据驱动器的几何信息填充hd_geometry,包含磁头,柱面,扇区等信息.
int (* getgeo)(struct block_device*, struct hd_geometry*);
3.gendisk结构体
使用gendisk结果提来描述一个独立的磁盘设备或分区.
//gendisk structure
struct gendisk{
/*前三个元素共同表征了一个磁盘的主,次设备号,同一个磁盘的各个分区共享一个主设备号*/
int major;/*主设备号*/
int first_minor;/*第一个次设备号*/
int minors;/*最大的次设备数,如果不能分区,则为*/
char disk_name[32];
struct hd_struct** part;/*磁盘上的分区信息*/
struct block_device_operations* fops;/*块设备操作,block_device_operations*/
struct request_queue* queue;/*请求队列,用于管理该设备IO请求队列的指针*/
void* private_data;/*私有数据*/
sector_t capacity;/*扇区数,512字节为个扇区,描述设备容量*/
//......
};
关于gendisk的操作:
/*分配一个gendisk结构体,此结构体是由内核动态分配的*/
struct gendisk* alloc_disk(int minors);
/*增加gendisk,来注册该设备,此动作应该在设备驱动初始化完毕,并能响应磁盘请求之后*/
void add_disk(struct gendisk* gd);
/*释放一个不再需要的磁盘*/
/**
***gendisk引用计数器:gendisk包含一个kobject成员.通过get_disk()&put_disk()函数来操作引用
***计数,此操作不需要驱动亲自完成.通常调用del_gendisk()会去掉gendisk的最终引用计数,但不是必
***须的.因此在del_gendisk()后gendisk结构体可能继续存在.
**/
/*设置gendisk容量*/
void set_capacity(struct gendisk* disk, sector_t size);
块设备中,最小的可寻址单元就扇区,常见扇区大小是512字节.扇区的大小是设备的物理属性,是所有块设备的基本单元,块设备无法对比扇区小的单元进行寻址和操作.不过许多块设备能够一次传输多个扇区.不管物理设备的真实扇区是多少,内核与块设备交互的扇区均以512字节为单位.所以set_capcity()函数以512字节为单位.