操作系统——linux文件系统初实现

简述:

0、ext2格式。

1、包括权限管理,精确到角色。

2、数据块采用连续分配(离散分配大家来弄吧)。

3、为实现间接索引,相信实现了目录,简介索引也不是问题吧。。

4、删除目录不支持递归删除。自己写去吧。

5、整体结构:

6、主要数据结构:

//超级块
struct SuperBlock
{
    int s_block_count;//block总个数
    int s_block_size;//block块的大小
    int s_inode_count;//inode总个数
    int s_datablock_count;//datablock总个数
    int s_free_inode_count;//空闲的inode个数
    int s_free_datablock_count;//空闲的数据block个数
    int s_inode_bitmap[INODE_COUNT];//inode节点位图 1使用 0未用
    int s_datablock_bitmap[DATABLOCK_COUNT];//数据块block位图 1使用 0未用
};
//磁盘索引节点INode
struct INode
{
    int i_key;//标识
    int i_type;//文件类型:正规文件、目录文件
    int i_size;//针对文件,文件长度;针对目录,目录项个数
    int i_group_id;//针对文件/目录,关联文件所属组别id 0管理员组 1用户组 2非法
    char i_create_time[30];//针对文件/目录
    char i_modify_time[30];//针对文件/目录
    int i_datablock_count;//针对文件,使用datablock数目;目录只能用一个
    int i_datablock[BLOCK_POINTER_NUMBER_IN_INODE];//一组datablock指针,前十个1级指针,第十一个2级指针,第十二个3级指针
};
//用户密码
struct PassWord
{
    int p_group_id;//权限仅验证到“组别级”,且假设:管理员组对所有文件/目录有增删改查权限;用户组对本组创建文件/目录有增删改查权限,对管理员组创建的文件/目录只有查(读)权限。
    char p_userName[USER_NAME_SIZE];
    char p_passWord[USER_PASSWORD_SIZE];
};
//目录项结构
struct DirFil
{
    char df_name[FILE_NAME_SIZE];//目录/文件名
    int df_inode_key;//目录/文件对应的inode编号
};
View Code

7、定义与全局变量:

# define GROUP_ADMIN 0//管理员组
# define GROUP_USER 1//普通用户组
# define GROUP_UNDEFINE 2//未定义,非法用户组

# define TYPE_FILE 0//普通文件
# define TYPE_DIRE 1//目录
# define TYPE_PASS 2//用户账号文件

# define BLOCK_SIZE 512//磁盘分块的大小
# define BLOCK_COUNT 500//磁盘分块的总数目,【包括超块、inode区的32块】
//区分DATA_BLOCK(存放数据的区域)与BLOCK(整个的磁盘区域)的区别
# define DATABLOCK_SIZE 512//每个DATABLOCK的大小
# define DATABLOCK_COUNT BLOCK_COUNT-36//数据BLOCK的块数,0-3超块,4-35共32块inode区

# define INODE_SIZE sizeof(struct INode)//每个inode的大小
# define INODE_COUNT 32//inode区的inode块数
# define BLOCK_POINTER_NUMBER_IN_INODE 12//inode节点中,指向数据块的指针个数,前十个1级,第十一个2级

# define INODE_START_BLOCK 4//inode区的开始BLOCK,从0计数
# define DATABLOCK_START_BLOCK 36//数据区的开始BLOCK,从0计数

# define USER_NAME_SIZE 15//单个用户名的长度
# define USER_PASSWORD_SIZE 15//单个密码的长度
# define PASSWORD_SIZE sizeof(struct PassWord)
# define PASS_WORD_COUNT BLOCK_SIZE/PASSWORD_SIZE//最多保存用户数

# define FILE_NAME_SIZE 15//文件、目录名的长度(字节)
# define DIR_FIL_SIZE sizeof(struct DirFil)
# define FILE_NUMBER_IN_DIRECTORY BLOCK_SIZE/DIR_FIL_SIZE//一个目录下的最多子目录或文件的总个数




//全局变量
const char fileSystemName[20]="FileSystem.txt";//模拟硬盘的文件名
FILE *fileSystemPointer;//模拟硬盘的文件的文件指针

struct SuperBlock superBlock;//超级块

struct INode *currentINode;//指向当前【目录】的inode
struct INode *tempINode;//跟多时候,是指向当前要处理的【文件】的inode

struct PassWord passWord[PASS_WORD_COUNT];//passWord区的用户账号和密码及用户组
struct PassWord curPW;//保存当前登陆的用户的账号和密码及用户组

struct DirFil currentDirFil[FILE_NUMBER_IN_DIRECTORY];//保存当前【目录】中的目录项
char abDir[200];//当前绝对路径

char curTime[30];

int iBM_lock=0;//inode位图锁 可能会多个进程同时访问 INodeAlloc
int dbBM_lock=0;//datablock位图锁 可能会多个进程同时访问 DatablockAlloc
View Code

8、增加文件:(思想:申请并初始化该文件的inode、datablock;更新文件父目录的inode、datablock;更新超块。)

int createFile()
{
    int i;
    char fileName[20];
    if(currentINode->i_size<FILE_NUMBER_IN_DIRECTORY)
    {
        printf("input file name:");
        fflush(stdin);
        scanf("%s",fileName);
        for(i=0;i<FILE_NUMBER_IN_DIRECTORY;i++)
        {
            if(strcmp(currentDirFil[i].df_name,fileName)==0)
            {
                printf("文件名已存在\n");
                return 0;
            }
        }
        char *input=(char *)malloc(BLOCK_SIZE*sizeof(char));
        printf("0:自己输入内容\n");
        printf("1:自动输入内容\n");
        printf("请选择:");
        fflush(stdin);
        scanf("%d",&i);
        if(i==0)
        {
            printf("自己输入内容,以“#”结束\n");
            while(1)
            {
                input[i]=getchar();
                if(input[i]==#)
                {
                    break;
                }
                i++;
                if(i%BLOCK_SIZE==0)
                {
                    input=(char *)realloc(input,BLOCK_SIZE*(i/BLOCK_SIZE+1)*sizeof(char));
                }
            }
            input[i]=\0;
        }
        else
        {
            i=0;
            while(i<1000)
            {
                input[i]=i%10+0;
                i++;
                if(i%BLOCK_SIZE==0)
                {
                    input=(char *)realloc(input,BLOCK_SIZE*(i/BLOCK_SIZE+1)*sizeof(char));
                }
            }
            input[i]=\0;
        }
        printf("input length is %d\n",strlen(input));
        printf("您输入的信息为:%s",input);

        //申请inode和datablock记录这些信息
        int ikey=INodeAlloc();
        if(ikey==-1)
        {
            return 0;
        }
        int datablockStartNumber=DatablockAlloc(strlen(input)/BLOCK_SIZE+1);
        if(datablockStartNumber==-1)
        {
            return 0;
        }
        else//将新建的文件的inode和datablock的信息补充完整
        {
            tempINode->i_key=ikey;
            tempINode->i_type=TYPE_FILE;
            tempINode->i_size=strlen(input)+1;//+1,把“\0”也要写进去
            tempINode->i_group_id=curPW.p_group_id;
            GetTime();
            strcpy(tempINode->i_create_time,curTime);
            strcpy(tempINode->i_modify_time,curTime);
            tempINode->i_datablock_count=(strlen(input)/BLOCK_SIZE+1);
            for(i=0;i<tempINode->i_datablock_count;i++)
            {
                tempINode->i_datablock[i]=datablockStartNumber+i;                            
            }
            fseek(fileSystemPointer,(DATABLOCK_START_BLOCK+datablockStartNumber)*BLOCK_SIZE,SEEK_SET);//将新建的文件内容写入datablock区
            //fwrite(input,sizeof(input),1,fileSystemPointer);不能sizeof(input),否则只能写进去4个=============================
            fwrite(input,strlen(input)+1,1,fileSystemPointer);//+1,把“\0”也要写进去

            fseek(fileSystemPointer,(INODE_START_BLOCK+ikey)*BLOCK_SIZE,SEEK_SET);//将新建的文件inode写入inode区
            fwrite(tempINode,sizeof(struct INode),1,fileSystemPointer);
        
            currentDirFil[currentINode->i_size].df_inode_key=ikey;//当前目录中添加一项子文件目录项
            strcpy(currentDirFil[currentINode->i_size].df_name,fileName);
            fseek(fileSystemPointer,(DATABLOCK_START_BLOCK+currentINode->i_datablock[0])*BLOCK_SIZE,SEEK_SET);//将当前目录更新后的信息写回datablock区
            fwrite(currentDirFil,sizeof(currentDirFil),1,fileSystemPointer);

            currentINode->i_size++;//当前目录的子文件数+1
            fseek(fileSystemPointer,(INODE_START_BLOCK+currentINode->i_key)*BLOCK_SIZE,SEEK_SET);//将当前inode更新后的inode写回inode区
            fwrite(currentINode,sizeof(struct INode),1,fileSystemPointer);
            
            fseek(fileSystemPointer,0,SEEK_SET);//将更新后的superBlock写回superBlock区
            fwrite(&superBlock,sizeof(struct SuperBlock),1,fileSystemPointer);

            free(input);
        }
    }
    else
    {
        printf("当前目录的子文件数目已达到最大\n");
        return 0;
    }
    printf("创建文件成功...\n");
    return 1;
}
View Code

9、删除目录:

int deleteFile()
{
    int i;
    char fileName[20];
    printf("input file name:");
    fflush(stdin);
    scanf("%s",fileName);
    for(i=0;i<FILE_NUMBER_IN_DIRECTORY;i++)
    {
        if(strcmp(currentDirFil[i].df_name,fileName)==0)
        {
            break;
        }
    }
    if(i==FILE_NUMBER_IN_DIRECTORY)
    {
        printf("当前目录下下没有文件%s\n",fileName);
        return 0;
    }
    else
    {
        ReadINode(currentDirFil[i].df_inode_key);
        if(tempINode->i_type!=TYPE_FILE)
        {
            printf("%s不是用户文件,可能是目录或系统文件,您不能使用该命令删除\n",fileName);
            return 0;
        }
        if(Authority()==0)
        {
            printf("您没有权限删除文件%s\n",fileName);
            return 0;
        }
        else
        {
            while(i<currentINode->i_size)//删除文件,更新当前目录datablock区
            {
                strcpy(currentDirFil[i].df_name,currentDirFil[i+1].df_name);
                currentDirFil[i].df_inode_key=currentDirFil[i+1].df_inode_key;
                i++;
            }
            fseek(fileSystemPointer,(DATABLOCK_START_BLOCK+currentINode->i_datablock[0])*BLOCK_SIZE,SEEK_SET);//将当前目录更新后的信息写回datablock区
            fwrite(currentDirFil,sizeof(currentDirFil),1,fileSystemPointer);
            currentINode->i_size--;//删除文件,更新当前目录indoe区
            fseek(fileSystemPointer,(INODE_START_BLOCK+currentINode->i_key)*BLOCK_SIZE,SEEK_SET);//将当前目录更新后的inode写回inode区
            fwrite(currentINode,sizeof(struct INode),1,fileSystemPointer);

            for(i=0;i<tempINode->i_datablock_count;i++)//删除文件,回收datablock区
            {
                superBlock.s_datablock_bitmap[tempINode->i_datablock[i]]=0;
            }
            superBlock.s_free_datablock_count+=tempINode->i_datablock_count;
            superBlock.s_inode_bitmap[tempINode->i_key]=0;//删除文件,回收inode区
            superBlock.s_free_inode_count++;            
            fseek(fileSystemPointer,0,SEEK_SET);//将更新后的superBlock写回superBlock区
            fwrite(&superBlock,sizeof(struct SuperBlock),1,fileSystemPointer);
        }
    }
    printf("删除文件成功...\n");
    return 1;
}
View Code

10、注意事项:

1)永远让currentINode指向当前目录的inode;tempINode指向当前要访问的子文件/子目录的inode;currentDirFile永远只想当前目录的datablock。

2)注意文件的读写方式,是wb、rb+还是什么,否则一定出错。

操作系统——linux文件系统初实现,古老的榕树,5-wow.com

郑重声明:本站内容如果来自互联网及其他传播媒体,其版权均属原媒体及文章作者所有。转载目的在于传递更多信息及用于网络分享,并不代表本站赞同其观点和对其真实性负责,也不构成任何其他建议。