Linux 2.6.11 下 MTD驱动情景实例分析(4)

add_mtd_partitions的最后调用add_mtd_device(&slave->mtd);把每个分区加进了mtd_table。这个函数在mtdcore.c中,前面提到的如果不分区,你可以直接把主分区做为参数加到mtd_table中。

Mtdcore.c如其名,它叫core是有原因的:它不调用mtd驱动各层次的任何外部函数(除了注册的回调函数)而只是输出函数,它管理着mtd_table。底层通过add_mtd_device和del_mtd_device来添加和删除原始设备(分区)。上层字符设备和块设备部分通过get_mtd_device和put_mtd_device来申请和释放分区等等。

int add_mtd_device(struct mtd_info *mtd)

{

       int i;

 

       down(&mtd_table_mutex);

 

       for (i=0; i < MAX_MTD_DEVICES; i++)

              if (!mtd_table[i]) {

                     struct list_head *this;

 

                     mtd_table[i] = mtd;

                     mtd->index = i;

                     mtd->usecount = 0;

 

                     DEBUG(0, "mtd: Giving out device %d to %s\n",i, mtd->name);

                     /* No need to get a refcount on the module containing

                        the notifier, since we hold the mtd_table_mutex */

                     list_for_each(this, &mtd_notifiers) {

                            struct mtd_notifier *not = list_entry(this, struct mtd_notifier, list);

                            not->add(mtd);//我的观点是如果你不打算动态增加和删除设备的话这一

//部分是没有必要的。系统初始化mtd设备时,这个链表也是空的。

                     }

                    

                     up(&mtd_table_mutex);

                     /* We _know_ we aren't being removed, because

                        our caller is still holding us here. So none

                        of this try_ nonsense, and no bitching about it

                        either. :) */

                     __module_get(THIS_MODULE);

                     return 0;

              }

      

       up(&mtd_table_mutex);

       return 1;

}

整个函数比较简单,在mtd_table中选择一个空位置放置你的分区的mtd_info。红色部分是比较难懂一点的:这个mtd_notifiers链表起什么作用?看看谁在这个链表中加了东西。register_mtd_user是唯一向这个链表添加了成员的,谁调了?看一下下面的程序

void register_mtd_user (struct mtd_notifier *new)

{

       int i;

 

       down(&mtd_table_mutex);

 

       list_add(&new->list, &mtd_notifiers);

 

      __module_get(THIS_MODULE);

      

       for (i=0; i< MAX_MTD_DEVICES; i++)

              if (mtd_table[i])

                     new->add(mtd_table[i]);

 

       up(&mtd_table_mutex);

}

 

static inline void mtdchar_devfs_init(void)

{

       devfs_mk_dir("mtd");

       register_mtd_user(&notifier);

}

int register_mtd_blktrans(struct mtd_blktrans_ops *tr)

{

       int ret, i;

 

       /* Register the notifier if/when the first device type is

          registered, to prevent the link/init ordering from fucking

          us over. */

       if (!blktrans_notifier.list.next)

              register_mtd_user(&blktrans_notifier);

    。。。。。省略n行

       return 0;

}

看来这个链表里面通常就只有两个成员。作用是当删除或添加一个mtd分区时告诉建立在其上的字符设备和块设备驱动。干什么?

当创建mtd字符设备时会调用mtdchar_devfs_init,他的notifier是这样的:

static struct mtd_notifier notifier = {

       .add = mtd_notify_add,

       .remove   = mtd_notify_remove,

};

static void mtd_notify_add(struct mtd_info* mtd)

{

       if (!mtd)

              return;

 

       devfs_mk_cdev(MKDEV(MTD_CHAR_MAJOR, mtd->index*2),

                    S_IFCHR | S_IRUGO | S_IWUGO, "mtd/%d", mtd->index);

             

       devfs_mk_cdev(MKDEV(MTD_CHAR_MAJOR, mtd->index*2+1),

                    S_IFCHR | S_IRUGO, "mtd/%dro", mtd->index);

}

这个devfs_mk_cdev应该就是自动创建devfs的节点吧,是不是就是不用再mknod了?我真的是linux新手,如果有人知道请不吝赐教,我只是从名字上猜测的。

 

总结一下:

内容版权声明:除非注明,否则皆为本站原创文章。

转载注明出处:https://www.heiqu.com/wzwyjx.html