snifer

【原创】基于字符型mtd流程分析

0
阅读(2414)

字符型mtd是嵌入式学习当中的一个难点,今天我就分析一下这个流程,以下是其源程序:

/driver/mtd/mtdchar.c

static int __init init_mtdchar(void){

...

       ret = __register_chrdev(MTD_CHAR_MAJOR, 0, 1 << MINORBITS, "mtd", &mtd_fops);

...

       ret = register_filesystem(&mtd_inodefs_type);

...

       register_mtd_user(&mtdchar_notifier);/*注册一个notify机器*/

...

}

static void __exit cleanup_mtdchar(void){

       unregister_mtd_user(&mtdchar_notifier);

       mntput(mtd_inode_mnt);

       unregister_filesystem(&mtd_inodefs_type);

       __unregister_chrdev(MTD_CHAR_MAJOR, 0, 1 << MINORBITS, "mtd");

}

module_init(init_mtdchar);

module_exit(cleanup_mtdchar);


其中:

register_mtd_user(&mtdchar_notifier);/*注册一个notify机器*/ 表示:

static struct mtd_notifier mtdchar_notifier = {

         .add = mtdchar_notify_add,

         .remove = mtdchar_notify_remove,

}; 当有新的mtd设备要注册时会调用notifier的add函数,以通知notifier有新的mtd设备注册了, 然后notifier就可以为其做相应的初始化工作

&mtd_fops表示:

static const struct file_operations mtd_fops = {

       .owner           = THIS_MODULE,

       .llseek            = mtd_lseek,

       .read              = mtd_read,

       .write             = mtd_write,

       .unlocked_ioctl      = mtd_unlocked_ioctl,

#ifdef CONFIG_COMPAT

       .compat_ioctl  = mtd_compat_ioctl,

#endif

       .open             = mtd_open,

       .release    = mtd_close,

       .mmap           = mtd_mmap,

#ifndef CONFIG_MMU

       .get_unmapped_area = mtd_get_unmapped_area,

#endif

};           

其中

       .open             = mtd_open,

表示为:

static int mtd_open(struct inode *inode, struct file *file){

...

       struct mtd_info *mtd;

       struct mtd_file_info *mfi;

       struct inode *mtd_ino;

...

       mtd = get_mtd_device(NULL, devnum);/*得到一个mtd设备*/

...

       put_mtd_device(mtd);/*归还一个mtd设备*/

       ...

} /* mtd_open */

以上程序中

       mtd = get_mtd_device(NULL, devnum);/*得到一个mtd设备*/

表示:

driver/mtd/mtdcore.c

struct mtd_info *get_mtd_device(struct mtd_info *mtd, int num){

struct mtd_info *ret = NULL, *other;

...

       err = __get_mtd_device(ret);

       if (err)

              ret = ERR_PTR(err);

...

       return ret;

}

int __get_mtd_device(struct mtd_info *mtd){

...

              err = mtd->get_device(mtd);

...

}

put_mtd_device(mtd);/*归还一个mtd设备*/

/driver/mtd/mtdcore.c

void put_mtd_device(struct mtd_info *mtd){

       mutex_lock(&mtd_table_mutex);

       __put_mtd_device(mtd);

       mutex_unlock(&mtd_table_mutex);

}

void __put_mtd_device(struct mtd_info *mtd){

...

       if (mtd->put_device)

              mtd->put_device(mtd);

...

}

mtd->put_device(mtd)的代码如下:

/include/linux/mtd.h

struct mtd_info {

...

       /* If the driver is something smart, like UBI, it may need to maintain()

        * its own reference counting. The below functions are only for driver.

        * The driver may register its callbacks. These callbacks are not

        * supposed to be called by MTD users */

       int (*get_device) (struct mtd_info *mtd);

       void (*put_device) (struct mtd_info *mtd);

};

他们之间的互相引用的关系就是这样,这样写好像不明显,下面我以CFI接口norflash芯片探测为例说明。