在ucOS中没有专门的文件系统,这里主要参考了linux0.11的内核的文件系统,采用的是Minix1.0。
其实文件系统就是把存储空间有合理的分配和整理,方便系统调用而设置的。
先介绍下我们公司板子的存储结构,我们用的是扩展的外部Flash,大小为512k,每个扇区的大小是256个字节,不算小,并且实现了写入写出的驱动,那么剩下的就是在这层驱动之上实现文件系统。
了解过minix文件系统的都应该知道,首先在第一个扇区写入文件系统的超级快,super_block,然后建立一张节点表,用于实现每个文件的节点信息保存,然后实现数据块表,用于实现数据存储块的申请,然后用几个扇区用于存放每个节点的信息,这里我规定节点数为120,根据实际需要,可以修改大小。
超级块的结构
typedef struct super_block {
unsigned short s_ninodes;
unsigned short s_nzones;
unsigned short s_imap_blocks;
unsigned short s_zmap_blocks;
unsigned short s_firstdatazone;
unsigned short s_log_zone_size;
unsigned long s_max_size;
unsigned short s_magic;
}super_block;
节点的结构
typedef struct {
unsigned short i_mode;
unsigned short i_uid;
unsigned long i_size;
unsigned long i_time;
unsigned char i_gid;
unsigned char i_nlinks;
unsigned short i_zone[9];
}i_inode;
这里规定“.”为父节点,“..”为当前节点。
首先初始化文件系统,相当于系统的格式化。
void filedisc_config(void)
{
unsigned char icode[15],dcode[256];
fileflash_config();
super_bk = Malloc(sizeof(super_block));
i_code = Malloc(sizeof(d_inode));
dir = Malloc(sizeof(dir_entry));
super_bk->s_ninodes = MAX_CODE_NO;
super_bk->s_nzones = MAX_SECTOR_NO;
super_bk->s_imap_blocks = 1;
super_bk->s_zmap_blocks = 1;
super_bk->s_firstdatazone = 32;
super_bk->s_log_zone_size = 0;
super_bk->s_max_size = 10000;
super_bk->s_magic = 0;
flash_write(0,0,(unsigned char *)&(*super_bk),sizeof(super_block));
memset(icode,0x00,sizeof(icode));
icode[0] |= 0x01;
flash_write(1,0,icode,15);
memset(dcode,0x00,sizeof(dcode));
memset(dcode,0x01,1);
flash_write(2,0,dcode,256);
i_code->i_mode = FILTER_FILE;
i_code->i_uid = 0;
i_code->i_size = 32;
i_code->i_time = 0;
i_code->i_gid = 0;
i_code->i_nlinks = 0;
memset(i_code->i_zone,0x00,sizeof(i_code->i_zone));
i_code->i_zone[0] = 1;
flash_icode_write(0,(unsigned char *)&(*i_code));
memset(dcode,0x00,sizeof(dcode));
*dcode = 0;
*(dcode + 1) = 0;
memcpy(dcode + 2,".",1);
*(dcode + 16) = 0;
*(dcode + 16 + 1) = 0;
memcpy(dcode + 16 * 1 + 2,"..",2);
flash_dcode_write(1,sizeof(dcode),dcode);
}
这里主要实现fopen,fread,fwrite,fclose等文件常用函数。
文件结构
typedef struct {
unsigned short f_mode;
unsigned short f_flags;
unsigned short f_count;
d_inode * f_inode;
off_t f_pos;
}file;
FP *file_open(unsigned char *name, char *mode)
{
FP *fp = NULL;
short i_code_id;
i_code_id = find_file(name);
if(i_code_id == 0)
return 0;
else
flash_icode_read(i_code_id,(unsigned char *)&(*i_code));
fp = Malloc(sizeof(FP));
if(strcmp(mode,"r") == 0){
fp->f_pos = 0;
fp->f_mode = READONLY;
}else if(strcmp(mode,"w") == 0){
fp->f_pos = 0;
fp->f_mode = WRITEONLY;
}else if(strcmp(mode,"w+") == 0){
fp->f_mode = WRITEADD;
fp->f_pos = fp->f_inode->i_size;
}
fp->f_inode = i_code;
return fp;
}
short file_read(FP *fp,unsigned char *str, short len)
{
short flen,num;
char index,i;
if(fp->f_inode->i_size < len)
flen = fp->f_inode->i_size;
else
flen = len;
index = flen /256;
num = 0;
for(i = 0;i <= index;i ++)
{
flash_dcode_read(fp->f_inode->i_zone[i],sizeof(dcode),dcode);
memcpy(str + num,dcode + fp->f_pos%256,(flen - i * 256) > 256 ? 256:flen - i * 256);
num += (flen - i * 256 > 256 ? 256:flen - i * 256);
fp->f_pos += (flen - i * 256 > 256 ? 256:flen - i * 256);;
if(num == flen)
break;
}
return num;
}
short file_write(FP *fp, unsigned char *str,short len)
{
short flen,offset,num = 0;
char index,i;
if(fp->f_inode->i_size + len > 256*10)
return 0;
else
flen = fp->f_inode->i_size + len;
index = flen /256;
offset = fp->f_pos%256;
for(i = 0;i <= index;i ++)
{
if(fp->f_inode->i_zone[i] == NULL)
fp->f_inode->i_zone[i] = get_d_code();
flash_dcode_read(fp->f_inode->i_zone[i],sizeof(dcode),dcode);
memcpy(dcode + offset,str + num,(len > (256 - offset)) ? (256 - offset):len);
flash_dcode_write(fp->f_inode->i_zone[i],sizeof(dcode),dcode);
num += (len > (256 - offset) ? 256 - offset:len);
fp->f_inode->i_size += (len > (256 - offset) ? 256 - offset:len);
fp->f_pos += (len > (256 - offset) ? 256 - offset:len);
len -= (len > (256 - offset) ? 256 - offset:len);
if(len == 0)
break;
else if(len > 0)
offset = 0;
}
flash_icode_write(fp->f_inode->i_uid,(unsigned char *)&(*i_code));
return num;
}
void file_close(FP *fp)
{
Free(fp);
}
int file_seek(FP *fp,unsigned short len,unsigned char mode)
{
switch(mode)
{
case SEEK_SET:
fp->f_pos = len;
break;
case SEEK_CUR:
fp->f_pos += len;
break;
case SEEK_END:
fp->f_pos = fp->f_inode->i_size ;
break;
}
return 0;
}
当然,这里还需要实现搜索文件,创建文件,创建文件夹等功能,就不再贴代码了,其核心思想完全借鉴的是minix的文件系统,只是实现方式因系统而异。