mount函数分析

来源:互联网 发布:北大开放数据 编辑:程序博客网 时间:2024/05/08 17:53

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

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这个一个系统调用涉及了很多的方面东西(文件系统,块设备驱动)。

0 0
原创粉丝点击