博文

目前显示的是 十月, 2011的博文

SD卡读写操作浅析

一个读写请求何时被读写,怎样读写,全看请求队列。以Goldfish平台上的MMC卡,我们来看看其请求队列都怎样设置的: mmc_blk_probe() 597     struct mmc_blk_data *md; 598     int err; 599 600     char cap_str[10]; 601 602     /* 603      * Check that the card supports the command class(es) we need. 604      */ 605     if (!(card->csd.cmdclass & CCC_BLOCK_READ)) 606         return -ENODEV; 607       608     md = mmc_blk_alloc(card); mmc_blk_probe->mmc_blk_alloc() 510     struct mmc_blk_data *md; 511     int devidx, ret; 512 513     devidx = find_first_zero_bit(dev_use, MMC_NUM_MINORS);//在dev_use中查找一个没有被用到的 514     if (devidx >= MMC_NUM_MINORS) 515         return ERR_PTR(-ENOSPC); 516     __set_bit(devidx, dev_use); 517 518     md = kzalloc(sizeof(struct mmc_blk_data), GFP_KERNEL); 519     if (!md) { 520         ret = -ENOMEM; 521         goto out; 522     } 523 524 525     /* 526      * Set the read-only status based on the supported commands 527      * and the write protect switch. 528      */

从Nand驱动到文件读写

Nand属于块设备。那么nand块设备是否像其他块设备那样,每次读写都经历一个“C/S”的过程呢? 我们在Goldfish Platform上,从nand的驱动注册开始,看看nand之上的yaffs2文件读写到底是怎样的一个过程。 本文主要是对自己在学习过程中遇到疑问做一个记录,同以前的文章一样,基本上只有流程,那些原理之类的东西,请同学们google吧。在下文中,有些代码可能会有重复,主要目的是不想让各位看官看的太累,跳来跳去,眼镜受不了啊。 代码是Android Kernel 2.6.29.整个记录过程比较仓促,难免会由认识上的错误,欢迎大家指正。 下面是Android在Goldfish Platform上的执行流程: <1> 377 static int __init init_mtdblock(void)         378 {  379     return register_mtd_blktrans(&mtdblock_tr); 380 }  在代码片段<1>中注册了一个struct mtd_blktrans_ops结构的mtdblock_tr,这个模块是系统在启动过程中加载的,从模块的init名字,可以看出,是针对mtd块设备的。由于在Linux中,Nand被归为MTD设备,MTD设备就是将nand设备封装了一下,让上层没有直接看到nand,而是看到的MTD。实际上,通过MTD来操作Nand,还是通过nand内部的驱动函数。不要把MTD看的太过神秘。如果还需要了解,请Google吧,我之前就是太较真了,一直没有弄明白,read the fucking code之后才算明白过来了。 这个mtd_blktrans_ops结构如下: <2>  32 struct mtd_blktrans_ops {  33     char *name;  34     int major;  35     int part_bits;  36     int blksize;  37     int blkshift;  38      39     /* Access functions */  40     int (*readsect)(struct mtd_blktrans

SD卡读写流程

本流程分析针对2.6.29Kernel on Goldfish Platform. SD卡的读写操作同其他块设备一样,都是异步的过程。当进程把request发到块设备请求队列后,在真正读写时,mq->thread进程会被激活。这个进程准确说属于内核线程,其函数执行主体如下: 44 static int mmc_queue_thread(void *d) 45 { 46     struct mmc_queue *mq = d; 47     struct request_queue *q = mq->queue; 48 49     current->flags |= PF_MEMALLOC; 50 51     down(&mq->thread_sem); 52     do { 53         struct request *req = NULL; 54 55         spin_lock_irq(q->queue_lock); 56         set_current_state(TASK_INTERRUPTIBLE); 57         if (!blk_queue_plugged(q)) 58             req = elv_next_request(q); 59         mq->req = req; 60         spin_unlock_irq(q->queue_lock); 61 62         if (!req) { 63             if (kthread_should_stop()) { 64                 set_current_state(TASK_RUNNING); 65                 break; 66             } 67             up(&mq->thread_sem); 68             schedule(); 69             down(&mq->thread_sem); 70             continue; 71         }