Linux内核MTD驱动程序与SD卡驱动程序(4)

2019-03-29 16:54

daemonize(“%sd”, tr->name);

//因为一些内核线程实际上要与信号打交道,daemonize()没有做后台化工作。

//我们不能仅调用exit_sighand函数,

//因为当最终退出时这样将可能引起oop(对象指针溢出错误)。 spin_lock_irq(¤t->sighand->siglock); sigfillset(¤t->blocked);

// 重新分析是否有挂起信号并设置或清除TIF_SIGPENDING标识给当前进程 recalc_sigpending();

spin_unlock_irq(¤t->sighand->siglock); spin_lock_irq(rq->queue_lock);

while (!tr->blkcore_priv->exiting) { struct request *req;

struct mtd_blktrans_dev *dev; int res = 0;

DECLARE_WAITQUEUE(wait, current); //声明当前进程的等待队列

req = elv_next_request(rq);//从块设备的请求队列中得到下一个请求

if (!req) {//如果请求不存在

//将设备的等待线程加到等待队列中

add_wait_queue(&tr->blkcore_priv->thread_wq, &wait); set_current_state(TASK_INTERRUPTIBLE); spin_unlock_irq(rq->queue_lock);

schedule(); //调度让CPU有机会执行等待的线程

remove_wait_queue(&tr->blkcore_priv->thread_wq, &wait); spin_lock_irq(rq->queue_lock); continue;

}

//如果请求存在

dev = req->rq_disk->private_data;//得到请求的设备 tr = dev->tr; //得到MTD翻译层设备操作函数集实例 spin_unlock_irq(rq->queue_lock);

down(&dev->sem); res = do_blktrans_request(tr, dev, req);//处理请求 up(&dev->sem);

spin_lock_irq(rq->queue_lock);

end_request(req, res); //从请求队列中删除请求并更新统计信息 }

spin_unlock_irq(rq->queue_lock);

//调用所有请求处理完的回调函数,并调用do_exit函数退出线程 complete_and_exit(&tr->blkcore_priv->thread_dead, 0); }

函数do_blktrans_request完成请求的具体操作,它调用MTD翻译层设备操作函数集实例中的具体函数来进行处理。函数do_blktrans_request分析如下: static int do_blktrans_request(struct mtd_blktrans_ops *tr, struct mtd_blktrans_dev *dev, struct request *req) {

unsigned long block, nsect; char *buf;

block = req->sector;

nsect = req->current_nr_sectors; buf = req->buffer;

if (!(req->flags & REQ_CMD)) return 0;

//如果读写的扇区数超出了块设备的容量,返回

if (block + nsect > get_capacity(req->rq_disk)) return 0;

//根据(rq)->flags & 1标识来判断操作方式,调用具体的设备操作函数 switch(rq_data_dir(req)) { case READ:

for (; nsect > 0; nsect--, block++, buf += 512) if (tr->readsect(dev, block, buf)) return 0; return 1;

case WRITE:

if (!tr->writesect) return 0;

for (; nsect > 0; nsect--, block++, buf += 512) if (tr->writesect(dev, block, buf)) return 0; return 1;

default:

printk(KERN_NOTICE “Unknown request %ld\\n”, rq_data_dir(req)); return 0; } }

图 函数register_mtd_user调用层次图

结构mtd_notifier是用于通知加上和去掉MTD原始设备。对于块设备来说,这个结构实例blktrans_notifier用来通知翻译层加上和去掉MTD原始设备。结构实例blktrans_notifier列出如下(在drivers/mtd/mtd_blkdevs.c中): static struct mtd_notifier blktrans_notifier = { .add = blktrans_notify_add,

.remove = blktrans_notify_remove, };

函数register_mtd_user注册MTD设备,通过分配通盘硬盘结构来激活每个MTD设备,使其出现在系统中。函数register_mtd_user调用层次图如上图。 函数register_mtd_user分析如下(在drivers/mtd/mtdcore.c中): static LIST_HEAD(mtd_notifiers);

void register_mtd_user (struct mtd_notifier *new) {

int i;

down(&mtd_table_mutex);

//将MTD块设备的通知结构实例blktrans_notifier加入 //到全局链表mtd_notifiers上

list_add(&new->list, &mtd_notifiers); //模块引用计数加1

__module_get(THIS_MODULE);

//对每个MTD块设备调用MTD通知结构实例的加设备函数 for (i=0; i< MAX_MTD_DEVICES; i++) if (mtd_table[i])

new->add(mtd_table[i]); up(&mtd_table_mutex); }

函数blktrans_notify_add通知MTD翻译层将设备加入到链表blktrans_majors中,并分配处理每个MTD分区对应的通用硬盘结构。 函数blktrans_notify_add分析如下(在drivers/mtd/mtd_blkdevs.c中):

static LIST_HEAD(blktrans_majors);

static void blktrans_notify_add(struct mtd_info *mtd) {

struct list_head *this;

if (mtd->type == MTD_ABSENT)//设备不存在 return;

//遍历每个MTD主块设备

list_for_each(this, &blktrans_majors) {

struct mtd_blktrans_ops *tr = list_entry(this, struct mtd_blktrans_ops, list); tr->add_mtd(tr, mtd); } }

函数mtdblock_add_mtd分配了MTD翻译层块设备结构,初始化后加到MTD翻译层块设备链表中,函数mtdblock_add_mtd分析如下:

static void mtdblock_add_mtd(struct mtd_blktrans_ops *tr, struct mtd_info *mtd) {

struct mtd_blktrans_dev *dev = kmalloc(sizeof(*dev), GFP_KERNEL); if (!dev) return;

memset(dev, 0, sizeof(*dev)); dev->mtd = mtd;

dev->devnum = mtd->index; dev->blksize = 512;

dev->size = mtd->size >> 9; dev->tr = tr;

if (!(mtd->flags & MTD_WRITEABLE)) dev->readonly = 1;

add_mtd_blktrans_dev(dev); }

函数add_mtd_blktrans_dev给每个MTD主设备分配设备号,并加到MTD设备链表对应位置上。然后给每个MTD设备分区分配一个通用硬盘结构,初始化这个通用硬盘结构后,再注册通用硬盘。这样通过通用硬盘就可以访问到每个MTD设备分区。


Linux内核MTD驱动程序与SD卡驱动程序(4).doc 将本文的Word文档下载到电脑 下载失败或者文档不完整,请联系客服人员解决!

下一篇:出色的主持

相关阅读
本类排行
× 注册会员免费下载(下载后可以自由复制和排版)

马上注册会员

注:下载文档有可能“只有目录或者内容不全”等情况,请下载之前注意辨别,如果您已付费且无法下载或内容有问题,请联系我们协助你处理。
微信: QQ: