redisread / HUGO_blog

存储Hugo博客项目

Home Page:http://hugo.jiahongw.com

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

大作业

redisread opened this issue · comments

Linux下一切皆文件

“一切皆是文件”是 Unix/Linux 的基本哲学之一。不仅普通的文件,目录、字符设备、块设备、 套接字等在 Unix/Linux 中都是以文件被对待;它们虽然类型不同,但是对其提供的却是同一套操作界面。

Superblock

是记录整个 filesystem 相关信息的地方, 没有 Superblock ,就没有这个 filesystem 了。他记录的信息主要有:

block 与 inode 的总量;
未使用与已使用的 inode / block 数量;
block 与 inode 的大小 (block 为 1, 2, 4K,inode 为 128 bytes);
filesystem 的挂载时间、最近一次写入数据的时间、最近一次检验磁盘 (fsck) 的时间等文件系统的相关信息;
一个 valid bit 数值,若此文件系统已被挂载,则 valid bit 为 0 ,若未被挂载,则 valid bit 为 1 。
Superblock 是非常重要的,因为文件系统的基本信息都写在这里, superblock 的大小为 1024bytes,此外,每个 block group 都可能含有 superblock !事实上除了第一个 block group 内会含有 superblock 之外,后续的 block group 不一定含有 superblock , 而若含有 superblock 则该 superblock 主要是做为第一个 block group 内 superblock 的备份咯,这样可以进行 superblock 的救援。

block bitmap (区块对照表)

从 block bitmap 当中可以知道哪些 block 是空的,如果你删除某些文件时,那些文件原本占用的 block 号码就得要释放出来, 此时在 block bitmap 当中相对应到该 block 号码的标志就得要修改成为『未使用中』。

inode bitmap (inode 对照表)

这个其实与 block bitmap 是类似的功能,只是 block bitmap 记录的是使用与未使用的 block 号码, 至于 inode bitmap 则是记录使用与未使用的 inode 号码。

rewind是C 程序中的库函数。

功 能: 将文件内部的位置指针重新指向一个流(数据流/文件)的开头。

注意:不是文件指针而是文件内部的位置指针,随着对文件的读写文件的位置指针(指向当前读写字节)向后移动。而文件指针是指向整个文件,如果不重新赋值文件指针不会改变。

获取当店的FcbLink:

//get curLink info
getFcbLink(curLink, curInode);
//目录信息链操作
/**
构建一个FcbLinkNode
finish
*/
void FileSystem::getFcbLinkNode(FcbLink pNode, Inode inode)
{
    if(pNode == NULL)
    {
        return;
    }
    pNode->fcb.id = inode.id;
    strcpy(pNode->fcb.name, inode.name);
    pNode->fcb.isDir = inode.isDir;
    pNode->fcb.blockId = inode.blockId;
    pNode->next = NULL;
}
/**
建立目录的信息链
finish
*/
void FileSystem::getFcbLink(FcbLink& curLink, Inode inode)
{
    if(curLink != NULL)
    {
        releaseFcbLink(curLink);
    }
    //目录本身节点
    //printf("start read dir self inode\n");
    curLink = new FcbLinkNode();
    getFcbLinkNode(curLink, inode);
    //printf("end read dir self inode\n");
    if(inode.length <= 0)
        return;

    //遍历建立子文件或子目录节点
    int i;
    unsigned int index;
    unsigned int blockId;
    unsigned int fileItem;
    Inode fileInode;
    FcbLink pNode;
    FcbLink link = curLink;
    unsigned long len = inode.length;//子文件或子目录数
    const int itemTotal = blockSize/itemSize;
    //遍历11个直接索引
    for(i = 0; i < 11; i++)
    {
        blockId = inode.addr[i];
        if(blockId > 0 || curInode.id == 0)
        {
            //遍历直接索引下itemTotal个fileItem项(文件i节点索引)
            for(index = 0; index < itemTotal; index++)
            {
                fileItem = getItem(blockId, index);
                //读取i子文件或子目录i节点
                if(fileItem > 0)
                {
                    getInode(&fileInode, fileItem);
                    pNode = new FcbLinkNode();
                    getFcbLinkNode(pNode, fileInode);
                    link->next = pNode;
                    link = pNode;
                    len--;
                    //printf("read dir item inode: id=%d, name=%s, index=%d\n", fileItem, fileInode.name, index);
                    if(len <= 0)
                    {
                        return;
                    }

                }
            }
        }
    }
    //遍历一级索引1个
    unsigned int addrBlockId = inode.addr[11];
    if(addrBlockId > 0)
    {
        //遍历一级索引下itemTotal个直接索引
        for(i = 0; i < itemTotal; i++)
        {
            blockId = inode.addr[i];
            if(blockId > 0)
            {
                //遍历直接索引下itemTotal个fileItem项(文件i节点索引)
                for(index = 0; index < itemTotal; index++)
                {
                    fileItem = getItem(blockId, index);
                    //读取i子文件或子目录i节点
                    if(fileItem > 0)
                    {
                        getInode(&fileInode, fileItem);
                        pNode = new FcbLinkNode();
                        getFcbLinkNode(pNode, fileInode);
                        link->next = pNode;
                        link = pNode;
                        len--;
                        //printf("read dir item inode: id=%d, name=%s, index=%d\n", fileItem, fileInode.name, index);
                        if(len <= 0)
                            return;
                    }
                }
            }
        }
    }
}

获取空闲的数据块

//blockImage区域操作
/**
寻找一个空闲的数据块,0号已被分配给根目录,返回值大于0表示找到
finish
*/
unsigned int FileSystem::getAvailableBlockId()
{
    if(superBlock.blockFree <= 0)
    {
        printf("no free block\n");
        return 0;
    }

    int i;
    for(i = 0; i < blockNum; i++)
    {
        if(blockBitmap[i] == 0)
        {
            //printf("find block %d\n", i);
            releaseBlock(i);
            return i;
        }
    }
    printf("no free block\n");
    return 0;
}

寻找空闲的Inode节点

//inodeImage区域操作
/**
寻找一个空闲的i节点块,0号已被分配给根目录,返回值大于0表示找到
finish
*/
unsigned int FileSystem::getAvailableInodeId()
{
    unsigned int i;
    for(i = 0; i < blockNum; i++)
    {
        if(inodeBitmap[i] == 0)
        {
            //printf("find inode %d\n", i);
            return i;
        }
    }
    return 0;
}

分配磁盘:

image