Chinaunix首页 | 论坛 | 博客
  • 博客访问: 308641
  • 博文数量: 63
  • 博客积分: 2018
  • 博客等级: 大尉
  • 技术积分: 694
  • 用 户 组: 普通用户
  • 注册时间: 2010-02-23 16:34
文章存档

2010年(63)

我的朋友

分类: LINUX

2010-08-27 20:15:42

md结构体:


struct mmc_blk_data

{ spinlock_t lock;

struct gendisk *disk;

struct mmc_queue queue;

unsigned int usage;

unsigned int read_only; };

1. gendisk struct gendisk (定义于 ) 是单独一个磁盘驱动器的内核表示. 事实上, 内核还使用 gendisk 来表示分区, 但是驱动作者不必知道这点. 在blk.c中,

有如下关于gendisk的初始化:

md->disk->major = MMC_BLOCK_MAJOR;

md->disk->first_minor = devidx << MMC_SHIFT;

md->disk->fops = &mmc_bdops;

md->disk->private_data = md;

md->disk->queue = md->queue.queue;

md->disk->driverfs_dev = &card->dev;

 

{{{ int major; int first_minor; int minors; 描述被磁盘使用的设备号的成员. 至少, 一个驱动器必须使用最少一个次编号. 如果你的驱动会是可分区的, 但是(并且大部分应当是), 你要分配一个次编号给每个可能的分区. 次编号的一个普通的值是 16, 它允许"全磁盘"设备盒 15 个分区. 一些磁盘驱动使用 64 个次编号给每个设备.

struct block_device_operations *fops; 设备操作集合.下面说明。

void *private_data; 块驱动可使用这个成员作为一个指向它们自己内部数据的指针.

struct gendisk 是一个动态分配的结构, 它需要特别的内核操作来初始化; 驱动不能自己分配这个结构. 相反, 你必须调用:

struct gendisk *alloc_disk(int minors);

minors 参数应当是这个磁盘使用的次编号数目; 注意你不能在之后改变 minors 成员并且期望事情可以正确工作. 当不再需要一个磁盘时, 它应当被释放, 使用:

void del_gendisk(struct gendisk *gd);

一个 gendisk 是一个被引用计数的结构(它含有一个 kobject). 有 get_disk 和 put_disk 函数用来操作引用计数, 但是驱动应当从不需要做这个. 正常地, 对 del_gendisk 的调用去掉了最一个 gendisk 的最终的引用, 但是不保证这样. 因此, 这个结构可能继续存在(并且你的方法可能被调用)在调用 del_gendisk 之后. 但是, 如果你删除这个结构当没有用户时(即, 在最后的释放之后, 或者在你的模块清理函数), 你可确信你不会再收到它的信息.

分配一个 gendisk 结构不能使系统可使用这个磁盘. 要做到这点, 你必须初始化这个结构并且调用 add_disk:

void add_disk(struct gendisk *gd);

这里记住一件重要的事情:一旦你调用add_disk, 这个磁盘是"活的"并且它的方法可被在任何时间被调用. 实际上, 这样的第一个调用将可能发生, 即便在 add_disk 返回之前; 内核将读前几个字节以试图找到一个分区表. 因此你不应当调用 add_disk 直到你的驱动被完全初始化并且准备好响应对那个磁盘的请求. }}}

2. mmc_queue 定义于mmc/card/queue.h struct mmc_queue

{ struct mmc_card *card;

  struct task_struct *thread;

  struct semaphore thread_sem;

  unsigned int flags;

  struct request *req;

  int (*issue_fn)(struct mmc_queue *, struct request *);

  void *data; struct request_queue *queue;

  struct scatterlist *sg;

  char *bounce_buf;

  struct scatterlist *bounce_sg;

  unsigned int bounce_sg_len; };

queue的初始化:

md->queue.issue_fn = mmc_blk_issue_rq;

md->queue.data = md;


block_device_operations

block_device_operations, 定义在 . 下面是一个对这个结构中的成员的简短的概览; 当我们进入 sbull 驱动的细节时详细重新访问它们.

int (*open)(struct inode *inode, struct file *filp);

int (*release)(struct inode *inode, struct file *filp);

就像它们的字符驱动对等体一样工作的函数; 无论何时设备被打开和关闭都调用它们. 一个字符驱动可能通过启动设备或者锁住门(为可移出的介质)来响应一个 open 调用. 如果你将介质锁入设备, 你当然应当在 release 方法中解锁.

int (*ioctl)(struct inode *inode, struct file *filp, unsigned int cmd, unsigned long arg);

实现 ioctl 系统调用的方法. 但是, 块层首先解释大量的标准请求; 因此大部分的块驱动 ioctl 方法相当短.

int (*media_changed) (struct gendisk *gd);

被内核调用来检查是否用户已经改变了驱动器中的介质的方法, 如果是这样返回一个非零值. 显然, 这个方法仅适用于支持可移出的介质的驱动器(并且最好给驱动一个"介质被改变"标志); 在其他情况下可被忽略.

struct gendisk 参数是内核任何表示单个磁盘; 我们将在下一节查看这个结构.

int (*revalidate_disk) (struct gendisk *gd);

revalidate_disk 方法被调用来响应一个介质改变; 它给驱动一个机会来进行需要的任何工作使新介质准备好使用. 这个函数返回一个 int 值, 但是值被内核忽略.

struct module *owner;

一个指向拥有这个结构的模块的指针; 它应当常常被初始化为 THIS_MODULE.

专心的读者可能已注意到这个列表一个有趣的省略: 没有实际读或写数据的函数. 在块 I/O 子系统, 这些操作由请求函数处理, 它们应当有它们自己的一节并且在本章后面讨论. 在我们谈论服务请求之前, 我们必须完成对磁盘注册的讨论.

 

 

阅读(1380) | 评论(1) | 转发(0) |
给主人留下些什么吧!~~

chinaunix网友2010-08-30 21:45:39

Download More than 1000 free IT eBooks: http://free-ebooks.appspot.com