mount函数分析

版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://blog.csdn.net/Destihang/article/details/51824579

首先判断挂载的类型是否符和已经定义好的文件系统类型。里面的实现方式是比较对应字符串是否相同。

mount_findfs(g_bdfsmap, filesystemtype);

其中g_bdfsmap就是已经定义好的文件系统类型。

static const struct fsmap_t g_bdfsmap[] =
 {
 #ifdef CONFIG_FS_FAT
     { "vfat", &fat_operations },
 #endif
 #ifdef CONFIG_FS_ROMFS
     { "romfs", &romfs_operations },
 #endif
 #ifdef CONFIG_FS_SMARTFS
     { "smartfs", &smartfs_operations },
 #endif
     { NULL,   NULL },
 };

根据文件路径找到相应的inode节点。//如何寻找的实现方式说明已经在之前的stat系统调用文章中说明。

接下来最核心的函数是

mops->bind(blkdrvr_inode, data, &fshandle);
该bind方法,该方法首先分配一个绑定的结构体空间

fs = (struct fat_mountpt_s *)kmm_zalloc(sizeof(struct fat_mountpt_s));
最终该结构体内容要被各种fat相关参数填充。

接下来就是fat文件系统挂载的核心函数

int fat_mount(struct fat_mountpt_s *fs, bool writeable)
一路跟踪下来,该函数中有关读写的都比较重要,我们先来看一下读函数(主要是读取一些扇区的信息)

int fat_hwread(struct fat_mountpt_s *fs, uint8_t *buffer,  off_t sector,
                unsigned int nsectors)
该函数主要是调用已经注册好的回调函数

inode->u.i_bops->read(inode, buffer,sector, nsectors);
而该回调函数又在注册块设备驱动的时候被赋值

int register_blockdriver(FAR const char *path,
                          FAR const struct block_operations *bops,
                          mode_t mode, FAR void *priv)
{
 <span style="white-space:pre">	</span>node->u.i_bops  = bops;
 #ifdef CONFIG_FILE_MODE
       node->i_mode    = mode;
 #endif
       node->i_private = priv;}

sd卡注册的块设备驱动应该是在相关mmcsd相关源文件中,而usb注册的块设备在相关usbhost相关源文件中。

首先介绍的sd的注册过程。

int mmcsd_slotinitialize(int minor, FAR struct sdio_dev_s *dev)
 {
   FAR struct mmcsd_state_s *priv;
   char devname[16];
   int ret = -ENOMEM;
 
   fvdbg("minor: %d\n", minor);
 
   /* Sanity check */
 
 #ifdef CONFIG_DEBUG
   if (minor < 0 || minor > 255 || !dev)
     {
       return -EINVAL;
     }
 #endif
 
   /* Allocate a MMC/SD state structure */
 
   priv = (FAR struct mmcsd_state_s *)kmm_malloc(sizeof(struct mmcsd_state_s));
   if (priv)
  {
       /* Initialize the MMC/SD state structure */
 
       memset(priv, 0, sizeof(struct mmcsd_state_s));
       sem_init(&priv->sem, 0, 1);
 
       /* Bind the MMCSD driver to the MMCSD state structure */
 
       priv->dev = dev;
 
       priv->dev_id = minor;
   /* Initialize the hardware associated with the slot */
 
       ret = mmcsd_hwinitialize(priv);
 
       /* Was the slot initialized successfully? */
 
       if (ret != OK)
         {
           if (ret == SDIO_OK)
             {
               return OK;
            }
           /* No... But the error ENODEV is returned if hardware initialization
            * succeeded but no card is inserted in the slot. In this case, the
            * no error occurred, but the driver is still not ready.
            */
 
           if (ret == -ENODEV)
             {
               /* No card in the slot (or if there is, we could not recognize
                * it).. Setup to receive the media inserted event
                */
 
               SDIO_CALLBACKENABLE(priv->dev, SDIOMEDIA_INSERTED);
 
               fvdbg("MMC/SD slot is empty\n");
             }
           else
             {
               /* Some other non-recoverable bad thing happened */
   fdbg("ERROR: Failed to initialize MMC/SD slot: %d\n", ret);
               goto errout_with_alloc;
             }
         }
 
 #if defined(CONFIG_DRVR_WRITEBUFFER) || defined(CONFIG_DRVR_READAHEAD)
       /* Initialize buffering */
 
 #warning "Missing setup of rwbuffer"
       ret = rwb_initialize(&priv->rwbuffer);
       if (ret < 0)
         {
 fdbg("ERROR: Buffer setup failed: %d\n", ret);
           goto errout_with_hwinit;
         }
 #endif
 
       /* Create a MMCSD device name */
 
       snprintf(devname, 16, "/dev/mmcsd%d", minor);
 
       /* Inode private data is a reference to the MMCSD state structure */
 
       ret = register_blockdriver(devname, &g_bops, 0, priv);

相关回调函数方法是

static const struct block_operations g_bops =
 {
   mmcsd_open,     /* open     */
   mmcsd_close,    /* close    */
   mmcsd_read,     /* read     */
 #ifdef CONFIG_FS_WRITABLE
   mmcsd_write,    /* write    */
 #else
   NULL,           /* write    */
 #endif
   mmcsd_geometry, /* geometry */
   mmcsd_ioctl     /* ioctl    */
 };

而在上面用到的read方法:

static ssize_t mmcsd_read(FAR struct inode *inode, unsigned char *buffer,size_t startsector, unsigned int nsectors);


最终发现所谓的上面的一系列方法实际上也是nuttx中mmc子系统的框架最终还会调用到最底层我们自己驱动的实现。下面就是框架和我们编写的联系的地方:

#define SDIO_LOCK(dev,state)  ((dev)->lock(dev,state))
#define SDIO_RESET(dev) ((dev)->reset(dev))
#define SDIO_STATUS(dev)        ((dev)->status(dev))
#define SDIO_WIDEBUS(dev,wide) ((dev)->widebus(dev,wide))
#define SDIO_CLOCK(dev,rate) ((dev)->clock(dev,rate))
#define SDIO_ATTACH(dev) ((dev)->attach(dev))
#define SDIO_SENDCMD(dev,cmd,arg) ((dev)->sendcmd(dev,cmd,arg))
#define SDIO_RECVSETUP(dev,buffer,nbytes) ((dev)->recvsetup(dev,buffer,nbytes))
#define SDIO_SENDSETUP(dev,buffer,nbytes) ((dev)->sendsetup(dev,buffer,nbytes))
#define SDIO_CANCEL(dev) ((dev)->cancel(dev))
#define SDIO_WAITRESPONSE(dev,cmd) ((dev)->waitresponse(dev,cmd))
#define SDIO_RECVR1(dev,cmd,R1) ((dev)->recvR1(dev,cmd,R1)) /* 48-bit */
#define SDIO_RECVR2(dev,cmd,R2) ((dev)->recvR2(dev,cmd,R2)) /* 136-bit */
#define SDIO_RECVR3(dev,cmd,R3) ((dev)->recvR3(dev,cmd,R3)) /* 48-bit */
#define SDIO_RECVR4(dev,cmd,R4) ((dev)->recvR4(dev,cmd,R4)) /* 48-bit */
#define SDIO_RECVR5(dev,cmd,R5) ((dev)->recvR5(dev,cmd,R5)) /* 48-bit */
#define SDIO_RECVR6(dev,cmd,R6) ((dev)->recvR6(dev,cmd,R6)) /* 48-bit */
#define SDIO_RECVR7(dev,cmd,R7) ((dev)->recvR7(dev,cmd,R7)) /* 48-bit */
#define SDIO_WAITENABLE(dev,eventset)  ((dev)->waitenable(dev,eventset))
#define SDIO_EVENTWAIT(dev,timeout)  ((dev)->eventwait(dev,timeout))
#define SDIO_CALLBACKENABLE(dev,eventset)  ((dev)->callbackenable(dev,eventset))

 {
 375 #ifdef CONFIG_SDIO_MUXBUS
 376         .lock             = xxx_lock,
 377 #endif
 378         .reset            = xxx_reset,
 379         .status           = xxx_status,
 380         .widebus          = xxx_widebus,
 381         .clock            = xxx_clock,
 382         .attach           = xxx_attach,
 383         .sendcmd          = xxx_sendcmd,
 384 #ifdef CONFIG_SDIO_BLOCKSETUP
 385         .blocksetup       = xxx_blocksetup,
 386 #endif
 387         .recvsetup        = xxx_recvsetup,
 388         .sendsetup        = xxx_sendsetup,
 389         .cancel           = xxx_cancel,
 390         .waitresponse     = xxx_waitresponse,
 391         .recvR1           = xxx_recvshortcrc,
 392         .recvR2           = xxx_recvlong,
 393         .recvR3           = xxx_recvshortcrc,
 394         .recvR4           = xxx_recvshortcrc,
 395         .recvR5           = xxx_recvshortcrc,
 396         .recvR6           = xxx_recvshortcrc,
 397         .recvR7           = xxx_recvshortcrc,
 398         .waitenable       = xxx_waitenable,
 399         .eventwait        = xxx_eventwait,
 400         .callbackenable   = xxx_callbackenable,
 401         .registercallback = xxx_registercallback,
 402 #ifdef CONFIG_SDIO_DMA
 403         .dmasupported     = xxx_dmasupported,
 404 #ifdef CONFIG_SDIO_PREFLIGHT
 405         .dmapreflight     = xxx_dmapreflight,
 406 #endif
 407         .dmarecvsetup     = xxx_dmarecvsetup,
 408         .dmasendsetup     = xxx_dmasendsetup,
 409 #endif
 410     },

最终这些回调函数会被上面的框架所调用,而实际上这些函数都是对寄存器的读写操作。

注意mmc中有两种模式一种是sd,一种是sdio。前一种主要是为sd卡,后者主要是为wifi,所以sdio也有相关的一系列回调函数。


接下来是usb挂载文件系统:

usb最初的注册函数是usbhost_msc_initialize。这个接口是usb框架提供的接口。

于是usbhost_registerclass(&g_storage);

最后调用注册块设备注册的函数register_blockdriver是 int usbhost_initvolume(FAR struct usbhost_state_s *priv);当然在这之前会分配相应的结构体空间。而在执行这一函数的前提是在connect的时候执行的。问题是谁去出发这个connect的条件,在查看nuttx源码的时候没有找到???

与mmc不相同的是usb首先调用相关框架的函数,然后再调用注册的回调函数,但是整体上都是相同的,跟着框架的逻辑走,最后调用回调函数,具体这两者的驱动的通信方式是怎么样的,那还需要我好好研究再做总结。


mount这个一个系统调用涉及了很多的方面东西(文件系统,块设备驱动)。

展开阅读全文

没有更多推荐了,返回首页