Chinaunix首页 | 论坛 | 博客
  • 博客访问: 17403
  • 博文数量: 5
  • 博客积分: 65
  • 博客等级: 民兵
  • 技术积分: 41
  • 用 户 组: 普通用户
  • 注册时间: 2012-09-28 19:28
文章分类
文章存档

2013年(3)

2012年(2)

我的朋友

分类: LINUX

2013-12-23 15:55:55

         以前两节基本可以挂在一个文件系统了,一方面注册一个文件系统类型,另外一个方面在挂在的时候读出超级块的信息,并构造一个根目录项的相关信息。

         这样可以通过

         Mount –t myfs /dev/mtdblk3 /mnt

         来挂载文件系统了,先别急着ls,因为相关的接口函数还没完成呢!

         上一节提到了文件系统中的三大操作结构体,为了满足大家ls的愿望,我们就先从文件夹的操作结构体开始吧。

static const struct file_operations myfs_dir_operations = {

         .read = generic_read_dir,

    .readdir = myfs_readdir,

         .llseek = generic_file_llseek,

};

         其实这个里面基本就实现了一个函数readdir,其实ls就是使用的这个接口函数。

static int myfs_readdir(struct file *f, void *dirent, filldir_t filldir)

{

         unsigned int offset,last,page_index,page_offset,inode_per_page,retlen,p;

         unsigned int err = 0,i ;

         struct inode *inode = f->f_dentry->d_inode;

         struct myfs_inode *llf_inode;

         struct myfs_sb_info *sbi = MYFS_S(inode->i_sb);

         struct mtd_info *mtd = sbi->mtd;

         offset = f->f_pos;//Linux中有“一切皆是文件”的概念,这个虽然是要读取一个文件夹下面的子文件的操作,但是传入参数还是一个file类型的指针。

//注意这儿的f->f_pos,在常规的文件中,这个字段用于保存我们读取,写入的offset。也可以通过lseek来改变这个字段。但是在文件夹中这个字段没有任何意义,因为文件夹的大小始终为0。但是在readdir中利用这个字段来保存每次读取的子文件的index

//如果大家稍微baidu看一下上层应用程序是如何使用readdir这个系统调用的话就大体知道这个函数应该如何来实现。

  while((p_dirent=readdir(p_dir)))

  {

       printf("%s\n",p_dirent->d_name);

}

Readdir系统调用每次读取一个文件的信息,通过while来循环读取,当没有文件可读时,返回NULL

         if(!offset)

                   offset++;

         myfs_trace("myfs_readdir: starting at %d", (int)offset);

         /* If the directory has changed since the open or last call to

      readdir, rewind to after the 2 canned entries. */

         if(offset >= MYFS_MAX_INODE_NUM)

                   return err;

         inode_per_page = sbi->myfs_sb.page_size/sizeof(struct myfs_inode);         //myfs只支持一级目录,所有的文件都存在于根目录之下。这儿计算每一个page可以容纳多少个目录inode节点,inode numberoffset的文件应该处于存储介质的什么位置。

         page_index = offset/inode_per_page;

         page_offset = offset%inode_per_page;

         last = mtd->writesize/sizeof(struct myfs_inode);

         for(p = page_index ; p myfs_sb.pages_per_block ;p++){

                   err = mtd->read(mtd,mtd->erasesize+p*mtd->writesize,mtd->writesize,&retlen,sbi->buf);

                   if(err){

                            myfs_trace("%s,mtd->read failed",__func__);

                            goto out;

                   }

                   llf_inode = (struct myfs_inode*)sbi->buf;

                   llf_inode += page_offset;

                   for( i = page_offset ;i < last ;i++,offset++,llf_inode++){

                                     /*root->i_ino == 0*/

                            if(llf_inode->attr != MYFS_ATTR_FILE )

                                     continue;

                            myfs_trace("find new file:%s",llf_inode->name);

                            /*find new file*/

                            if(filldir(,llf_inode->name,strlen(llf_inode->name),offset,llf_inode->inode_no,DT_REG) < 0){//找到新文件啦,那么就把文件系统填充在dirent,然后系统调用就会返回给应用程序。

                                     goto out;

                            }

                   }

         }

         f->f_pos = offset;//这儿可以看出f->f_pos存储的是上一次找到文件的位置,那么下一次就接着从这个位置开始往后找。

out:

         return err;

}

         好了,这样我们在挂载之后就可以使用ls命令来列出根目录下面的所有文件啦!!

阅读(943) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~