有没有办法在 C 中为 i_block 创建迭代器样式函数?
Is there a way to create an iterator style function for i_block in C?
我正在为一个学校项目处理一些 ext2 文件系统的东西(实现 ls、mkdir 之类的东西),我发现我正在为需要遍历 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;
}
如有任何建议,我们将不胜感激!谢谢
这是我现在要做的
感谢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;
}
我正在为一个学校项目处理一些 ext2 文件系统的东西(实现 ls、mkdir 之类的东西),我发现我正在为需要遍历 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;
}
如有任何建议,我们将不胜感激!谢谢
这是我现在要做的
感谢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;
}