题目描述:
编写一个函数实现Linux文件寻址的算法,即读取文件当前位置到物理存储位置的转换函数,需要给出运行的测试数据,可以假设和模拟需要的数据和结构。即编写一个函数unsigned long ltop(unsigned long logblkNum). 计算逻辑块号logblkNum所对应的物理块的块号。
#include<stdio.h>
#include<stdlib.h>
#include<time.h>
#define index (12) //直接索引块数目
#define first_index (1 << 7) // 一级索引块数目
#define second_index (1 << 14)
#define third_index (1 << 21)
#define blksize 512 //物理块大小
#define blknumsize 4 //索引块大小
#define index_blk_sum (15 + first_index + second_index + third_index) //索引块总数
struct inode
{
unsigned long i_block[15];
}inode;
FILE *fp;
int bitmap[index_blk_sum] = {0};
int find_bitmap(int curpos)
{
int j, k;
for(j = k = curpos; bitmap[j] == 1 && bitmap[k] == 1 && k >= 0 && j < index_blk_sum; ++j, --k);
if(j < index_blk_sum && bitmap[j] == 0)
return j;
else if(k >= 0 && bitmap[k] == 0)
return k;
}
void print(int buf[])
{
for(int i = 0; i < first_index; ++i)
printf("%d ", buf[i]);
printf("\n");
}
void dirty(int pos)
{
bitmap[pos] = 1;
}
void init_inode()
{
for(int i = 0; i < 15; ++i)
{
int tmp = rand() % index_blk_sum;
if(bitmap[tmp] == 1)
{
int j = find_bitmap(tmp);
inode.i_block[i] = j;
dirty(j);
}
else
{
inode.i_block[i] = tmp;
dirty(tmp);
}
}
}
void init_filesys()
{
long long bufsize = index_blk_sum * blksize;
char *buf = malloc(sizeof(char) * bufsize);
fwrite(buf, sizeof(buf), 1, fp);
free(buf);
}
void do_random(int buf[], int n)
{
for(int i = 0; i < n; ++i)
{
int tmp = rand() % index_blk_sum;
if(bitmap[tmp] == 1)
{
int j = find_bitmap(tmp);
buf[i] = j;
dirty(j);
}
else
{
buf[i] = tmp;
dirty(tmp);
}
}
}
void put_inode()
{
fseek(fp, 0, SEEK_SET);
fwrite(&inode, sizeof(inode), 1, fp);
}
void put_direct_index(unsigned long offset)
{
int buf[first_index] = {0};
do_random(buf, first_index);
fseek(fp, offset, SEEK_SET);
fwrite(buf, sizeof(int), first_index, fp);
}
void put_first_index()
{
unsigned int buf_1[first_index];
put_direct_index(inode.i_block[13] * blksize);
fseek(fp, inode.i_block[13] * blksize, SEEK_SET);
fread(buf_1, sizeof(int), first_index, fp);
for(int i = 0; i < first_index; ++i)
put_direct_index(buf_1[i] * blksize);
}
void put_second_index()
{
unsigned int buf_1[first_index] = {0};
unsigned int buf_2[first_index] = {0};
put_direct_index(inode.i_block[14] * blksize);
fseek(fp, inode.i_block[14] * blksize, SEEK_SET);
fread(buf_1, sizeof(int), first_index, fp);
for(int i = 0; i < first_index; ++i)
{
put_direct_index(buf_1[i] * blksize);
fseek(fp, buf_1[i] * blksize, SEEK_SET);
fread(buf_2, sizeof(int), first_index, fp);
for(int j = 0; j < first_index; ++j)
{
put_direct_index(buf_2[j] * blksize);
}
}
}
unsigned long ltop(unsigned long l_addr)
{
unsigned int buf_1[first_index] = {0};
unsigned int buf_2[first_index] = {0};
unsigned int buf_3[first_index] = {0};
if(l_addr < 0 || l_addr > index_blk_sum - 1)
return index_blk_sum;
else
{
if(l_addr < index)
{
return inode.i_block[l_addr];
}
else if(l_addr < (index + first_index))
{
fseek(fp, inode.i_block[12] * blksize, SEEK_SET);
fread(buf_1, sizeof(int), first_index, fp);
return buf_1[l_addr - index];
}
else if(l_addr < (index + first_index + second_index))
{
fseek(fp, inode.i_block[13] * blksize, SEEK_SET);
fread(buf_1, sizeof(int), first_index, fp);
fseek(fp, buf_1[(l_addr - (index + first_index)) / first_index] * blksize, SEEK_SET);
fread(buf_2, sizeof(int), first_index, fp);
return buf_2[(l_addr - (index + first_index)) % first_index];
}
else if(l_addr < (index_blk_sum))
{
fseek(fp, inode.i_block[14] * blksize, SEEK_SET);
fread(buf_1, sizeof(int), first_index, fp);
fseek(fp, buf_1[(l_addr - (index + first_index + second_index)) / second_index] * blksize, SEEK_SET);
fread(buf_2, sizeof(int), first_index, fp);
fseek(fp, buf_2[(l_addr - (index + first_index + second_index)) % second_index / first_index] * blksize, SEEK_SET);
fread(buf_3, sizeof(int), first_index, fp);
return buf_3[(l_addr - (index + first_index + second_index)) % second_index % first_index];
}
}
}
int main()
{
srand((unsigned)time(NULL));
unsigned long l_addr;
fp = fopen("ext2", "w+");
if(fp == NULL)
{
printf("create filesys error!\n");
exit(0);
}
init_inode();
init_filesys();
put_inode();
put_direct_index(inode.i_block[12] * blksize);
put_first_index();
put_second_index();
while(scanf("%ld", &l_addr) != EOF)
{
unsigned long p_addr = ltop(l_addr);
if(p_addr < index_blk_sum)
printf("logical blknum %ld to physical blknum %ld\n", l_addr, p_addr);
else
printf("out of memory\n");
}
fclose(fp);
return 0;
}