【原创】基于字符型mtd流程分析
0赞字符型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芯片探测为例说明。