有没有办法在 C 中为 i_block 创建迭代器样式函数?

王牌C

我正在为学校项目(实现 ls、mkdir 之类的东西)处理一些 ext2 文件系统内容,并且发现我正在为需要遍历 inode 的 i_block 的任务生成大量冗余代码。我有函数来计算 dir 条目的数量,搜索 dir 条目以查找 strcmp 名称匹配,读取数据,写入数据......遍历 i_block 似乎对许多问题都很常见。我正在尝试为 i_block 编写类似于迭代器的东西来消除这种冗余。

我想知道这样做的好方法是什么?是否有在 linux 系统代码中完成此操作或类似操作的示例?或者这只是一个坏主意。

到目前为止我想出的代码:

    // returns block number located at iter position
    // accepts a minode which is a struct wrapping an inode (in memory inode)
    // accepts an iter which will self mutate and should start at 0
    int iter_i_block(minode *mip, int *iter) {
      static char buf[BLKSIZE]; // static buffer
      // buffer number used to check if a new block needs to be read in
      static int bufno;
      // inode number used to determine if we are working on a new inode
      static int ino; 
      // block number to return
      int bno;
      // flag for if this a different inode than last time
      int new_ino = 0;

      if (ino != mip->ino) {
        ino = mip->ino;
        new_ino = 1;
      }
      // direct blocks
      if (*iter < 12) {
        bno = mip->inode.i_block[*iter];
        (*iter)++;
        bufno = bno;
        return bno;
      }

      // indirect blocks
      if (*iter < 12 + BLKSIZE_1024 / sizeof(int)) {
        if (!mip->inode.i_block[12])
          return 0;
        if (new_ino || bufno != 12)
          get_block(mip->mount_entry, mip->inode.i_block[12], buf);
        bufno = 12;
        bno = *((int *)buf + (*iter - 12));
        (*iter)++;
        return bno;
      }

      // double indirect blocks (not shown)
      // triple indirect blocks (not shown)
      return 0;
    }

任何建议表示赞赏!谢谢

王牌C

这是我现在要做的

感谢Gil Hamilton建议使用结构

typedef struct blk_iter {
  struct minode *mip;
  // buf contains the nth block
  unsigned int nth;
  // direct block (buf), indirection block(map1),
  // double indirection(map2), triple indirection(map3);
  char buf[BLKSIZE_1024], map1[BLKSIZE_1024], map2[BLKSIZE_1024],
      map3[BLKSIZE_1024];
} blk_iter;

// returns a char* buffer of BLKSIZE on success
// null on failure (nothing more to read)
// must start from nth = -1
char *get_blk(blk_iter *it, int lbk) {
  // calculations for convience, could be macros
  int blks_per = BLKSIZE_1024 / sizeof(int);
  int direct_start = 0, direct_end = 12, indirect_start = direct_end,
      indirect_end = direct_end + blks_per, double_start = indirect_end,
      double_end = indirect_end + blks_per * blks_per,
      triple_start = double_end,
      triple_end = double_end + blks_per * blks_per * blks_per;
  // pointers for shorter names
  unsigned int *i_block = it->mip->inode.i_block;
  mount_entry *me = it->mip->mount_entry;
  // null check
  if (!it || !it->mip)
    return 0;
  // get blocks based on lbk
  if (lbk < direct_end) {
    // get direct block
    get_block(me, i_block[lbk], it->buf);
  } else if (lbk < indirect_end) {
    // get indirect block
    if (!(it->nth >= indirect_start && it->nth < indirect_end))
      // check if map1 cached
      get_block(me, i_block[12], it->map1);
    get_block(me, it->map1[lbk - indirect_start], it->buf);
  } else if (lbk < double_end) {
    // get double indirect block
    if (!(it->nth >= double_start && it->nth < double_end))
      // check if map2 cached
      get_block(me, i_block[13], it->map2);
    if (!((lbk - double_start) / blks_per ==
          (it->nth - double_start) / blks_per))
      // check if map1 cached
      get_block(me, it->map2[(lbk - double_start) / blks_per], it->map1);
    get_block(me, it->map1[(lbk - double_start) % blks_per], it->buf);
  } else if (lbk < triple_end) {
    // triple  indirect blocks
    if (!(it->nth >= triple_start && it->nth < triple_end))
      // check if map3 cached
      get_block(me, i_block[12], it->map3);
    if (!((lbk - triple_start) / (blks_per * blks_per) ==
          (it->nth - triple_start) / (blks_per * blks_per)))
      // check if map2 cached
      get_block(me, it->map3[(lbk - triple_start) / (blks_per * blks_per)],
                it->map2);
    if (!((lbk - triple_start) / blks_per ==
          (it->nth - triple_start) / blks_per))
      // check if map1 cached
      get_block(me, it->map2[(lbk - triple_start) / blks_per], it->map1);
    get_block(me, it->map1[(lbk - triple_start) % blks_per], it->buf);
  }
  it->nth = lbk;
  return it->buf;
}

本文收集自互联网,转载请注明来源。

如有侵权,请联系 [email protected] 删除。

编辑于
0

我来说两句

0 条评论
登录 后参与评论

相关文章

有没有办法在C ++中复合函数?

有没有办法为C ++中的模板函数动态赋值?

有没有办法在C ++中创建未知数量的变量的构造函数?

有没有办法在 C++ 中创建一个组合函数的数组?

有没有办法在浏览器中编译代码(C / C ++)?

有没有办法在C ++中的方法中替换函数

有没有办法在 C 中创建动态类型分配

在 C# 中,有没有办法直接从数组创建 List 而无需复制?

有没有办法在 C++ 中创建类型变量?

有没有办法在 Xamarin C# 中的 ListView 列上方创建列名

有没有办法让函数将运算符作为c ++中的参数?

有没有办法将对象的字段隐式传递给C ++中的函数

有没有办法知道超类构造函数中调用对象的子类?C ++

有没有办法在C中获取函数的参数名称

有没有办法从 C++ 中的函数返回自定义结构?

有没有办法在C#中获取extern方法的函数指针

有没有办法在 c# 中的 int[][] 上使用函数相交

有没有办法从 C++ 函数中的 int 变量返回浮点数?

有没有办法告诉编译器忽略C中的某些代码块?

有没有办法在C预处理器中执行任意代码?

有没有办法在C ++编译器中禁用复制省略

有没有办法在浏览器中本地运行C程序?

有没有办法在 C# 中检查服务器套接字的状态?

有没有办法在 C 中操作预处理器定义范围

有没有办法在 React 中为装饰器创建组合函数?

有没有办法创建一个速记映射以传递给 C++ 中的函数?

有没有办法在C#中创建DLL并在SQL Server中使用DLL的函数

有没有办法在 C 中倒带 stdin?

在C ++中,有没有办法从具有返回类型为string&的函数中不返回任何内容?