目录

1、详解FAT12文件系统

2、实验

1、向虚拟软盘写入文件

2、读取软盘文件系统信息

3、在根目录中查找目标文件

4、读取目标文件到内存

3、小结


1、FAT12文件系统

文件系统

- 存储介质上组织文件数据的方法(数据组织的方式)

文件系统示例

- FAT12是DOS时代的早期文件系统

- FAT12结构非常简单,一直沿用于软盘

- FAT12的基本组织单位

字节(Byte):基本数据单位

扇区(Sector):磁盘中的最小数据单元

簇(Cluster):一个或多个扇区

深入FAT12文件系统

FAT12文件系统由引导区,FAT表,根目录项表和文件数据区组成。

FAT12的主引导区

主引导区存储的比较重要的信息是文件系统的类型,文件系统逻辑扇区总数,

每簇包含的扇区数等。主引导区最后以0x55AA两个字节作为结束,共占用一个扇区。

二进制分析:(data.img由后文生成)

根目录区的大小和位置

可以看到根目录区起始于第19扇区

根目录区的目录项

根目录区由目录项构成,每一个目录项代表根目录中的一个文件索引。

//创建 RootEntry 结构体类型
struct RootEntry
{char DIR_Name[11];uchar DIR_Attr;uchar reserve[10];ushort DIR_WrtTime;ushort DIR_WrtDate;ushort DIR_FstClus;uint DIR_FileSize;
};

FAT表 - FAT12的数据组织核心

- FAT1和FAT2是相互备份的关系 ,数据内容完全一致

- FAT表是一个关系图,记录了文件数据的先后关系

- 每一个FAT表项占用12比特

- FAT表的前2个表项规定不使用

FAT表中的先后关系

- 以簇(扇区)为单位存储文件数据(这里一簇等于一扇区大小)

- 每个表项(vec[i])表示文件数据的实际位置(簇)

(1)DIR_FstClus表示文件第0簇(扇区)的位置

(2)vec[DIR_FstClus]表示文件第1簇(扇区)的位置

(3)vec[vec[DIR_FstClus]]表示文件第2簇(扇区)的位置...

FAT12数据物理组织示意

FAT12数据逻辑组织示意


2、实验

模拟Boot 查找目标文件(Loader),并读取文件的内容!- 突破Boot512字节限制的解决方案

解决方案(★)

- 使用FAT12对软盘(data.img)进行格式化

- 编写可执行程序(Loader),并将其拷贝到软盘中

- 主引导程序(Boot)在文件系统中查找Loader

- 将Loader复制到内存中,并跳转到入口处执行


1、向虚拟软盘写入文件

实验:往虚拟软盘中写入文件

- 原材料:FreeDos,Bochs,bximage

- 步骤:

① 创建虚拟软盘data.img

② 在FreeDos中进行格式化(FAT12)

③ 将data.img挂载到Linux中,并写入文件

1、先创建一个虚拟软盘 data.img

2、修改bochsrc 配置文件,freedos.img 作为启动软盘(A盘),将软盘data.img作为B盘插入

###############################################################
# Configuration file for Bochs
################################################################ how much memory the emulated machine will have
megs: 32# filename of ROM images
romimage: file=/usr/local/share/bochs/BIOS-bochs-latest
vgaromimage: file=/usr/share/vgabios/vgabios.bin# what disk images will be used
floppya: 1_44=freedos.img, status=inserted
floppyb: 1_44=data.img, status=inserted# choose the boot disk.
boot: floppy# where do we send log messages?
# log: bochsout.txt# disable the mouse
mouse: enabled=0# enable key mapping, using US layout as default.
keyboard_mapping: enabled=1, map=/usr/local/share/bochs/keymaps/x11-pc-us.map

启动bochs

3、将data.img挂载到Linux中,并写入loader文件

成功向FAT12格式的软盘写入文件


2、读取软盘文件系统信息

实验:读取data.img中的文件系统信息

步骤:

创建Fat12Header结构体类型

使用文件流读取前512字节的内容

解析并打印相关的信息

#include <QtCore/QCoreApplication>
#include <QFile>
#include <QDataStream>
#include <QDebug>#pragma pack(push)
#pragma pack(1)struct Fat12Header
{char BS_OEMName[8];    // OEM字符串,必须为8个字符,不足以空格填空ushort BPB_BytsPerSec; // 每扇区字节数uchar BPB_SecPerClus;  // 每簇占用的扇区数ushort BPB_RsvdSecCnt; // Boot占用的扇区数uchar BPB_NumFATs;     // FAT表的记录数ushort BPB_RootEntCnt; // 最大根目录文件数ushort BPB_TotSec16;   // 每个FAT占用扇区数uchar BPB_Media;       // 媒体描述符ushort BPB_FATSz16;    // 每个FAT占用扇区数ushort BPB_SecPerTrk;  // 每个磁道扇区数ushort BPB_NumHeads;   // 磁头数uint BPB_HiddSec;      // 隐藏扇区数uint BPB_TotSec32;     // 如果BPB_TotSec16是0,则在这里记录uchar BS_DrvNum;       // 中断13的驱动器号uchar BS_Reserved1;    // 未使用uchar BS_BootSig;      // 扩展引导标志uint BS_VolID;         // 卷序列号char BS_VolLab[11];    // 卷标,必须是11个字符,不足以空格填充char BS_FileSysType[8];// 文件系统类型,必须是8个字符,不足填充空格
};#pragma pack(pop)void PrintHeader(Fat12Header& rf, QString p)
{QFile file(p);if( file.open(QIODevice::ReadOnly) ){QDataStream in(&file);file.seek(3);in.readRawData(reinterpret_cast<char*>(&rf), sizeof(rf));rf.BS_OEMName[7] = 0;rf.BS_VolLab[10] = 0;rf.BS_FileSysType[7] = 0;qDebug() << "BS_OEMName: " << rf.BS_OEMName;qDebug() << "BPB_BytsPerSec: " << hex << rf.BPB_BytsPerSec;qDebug() << "BPB_SecPerClus: " << hex << rf.BPB_SecPerClus;qDebug() << "BPB_RsvdSecCnt: " << hex << rf.BPB_RsvdSecCnt;qDebug() << "BPB_NumFATs: " << hex << rf.BPB_NumFATs;qDebug() << "BPB_RootEntCnt: " << hex << rf.BPB_RootEntCnt;qDebug() << "BPB_TotSec16: " << hex << rf.BPB_TotSec16;qDebug() << "BPB_Media: " << hex << rf.BPB_Media;qDebug() << "BPB_FATSz16: " << hex << rf.BPB_FATSz16;qDebug() << "BPB_SecPerTrk: " << hex << rf.BPB_SecPerTrk;qDebug() << "BPB_NumHeads: " << hex << rf.BPB_NumHeads;qDebug() << "BPB_HiddSec: " << hex << rf.BPB_HiddSec;qDebug() << "BPB_TotSec32: " << hex << rf.BPB_TotSec32;qDebug() << "BS_DrvNum: " << hex << rf.BS_DrvNum;qDebug() << "BS_Reserved1: " << hex << rf.BS_Reserved1;qDebug() << "BS_BootSig: " << hex << rf.BS_BootSig;qDebug() << "BS_VolID: " << hex << rf.BS_VolID;qDebug() << "BS_VolLab: " << rf.BS_VolLab;qDebug() << "BS_FileSysType: " << rf.BS_FileSysType;file.seek(510);uchar b510 = 0;uchar b511 = 0;in.readRawData(reinterpret_cast<char*>(&b510), sizeof(b510));in.readRawData(reinterpret_cast<char*>(&b511), sizeof(b511));qDebug() << "Byte 510: " << hex << b510;qDebug() << "Byte 511: " << hex << b511;}file.close();
}int main(int argc, char *argv[])
{QCoreApplication a(argc, argv);Fat12Header f12;PrintHeader(f12, "E:\\data.img");return a.exec();
}

200H = 512

实验结论

1.FreeDos中的format程序在格式化软盘的时候自动在第0扇区生成了一个主引导程序,这个主引导程序只打印一个字符串

2.文件格式和文件系统都是用于定义数据如何存放的规则,只要遵循这个规则就能够成功读写目标数据(参考PE文件结构)


3、在根目录中查找目标文件

如何在FAT12根目录中查找是否存在目标文件?

实验:读取FAT12文件系统的根目录信息

#include <QtCore/QCoreApplication>
#include <QFile>
#include <QDataStream>
#include <QDebug>
#include <QVector>
#include <QByteArray>
#include <stdio.h>#pragma pack(push)
#pragma pack(1)struct Fat12Header
{char BS_OEMName[8];ushort BPB_BytsPerSec;uchar BPB_SecPerClus;ushort BPB_RsvdSecCnt;uchar BPB_NumFATs;ushort BPB_RootEntCnt;ushort BPB_TotSec16;uchar BPB_Media;ushort BPB_FATSz16;ushort BPB_SecPerTrk;ushort BPB_NumHeads;uint BPB_HiddSec;uint BPB_TotSec32;uchar BS_DrvNum;uchar BS_Reserved1;uchar BS_BootSig;uint BS_VolID;char BS_VolLab[11];char BS_FileSysType[8];
};struct RootEntry
{char DIR_Name[11];uchar DIR_Attr;uchar reserve[10];ushort DIR_WrtTime;ushort DIR_WrtDate;ushort DIR_FstClus;uint DIR_FileSize;
};#pragma pack(pop)void PrintHeader(Fat12Header& rf, QString p)
{QFile file(p);if( file.open(QIODevice::ReadOnly) ){QDataStream in(&file);file.seek(3);in.readRawData(reinterpret_cast<char*>(&rf), sizeof(rf));rf.BS_OEMName[7] = 0;rf.BS_VolLab[10] = 0;rf.BS_FileSysType[7] = 0;qDebug() << "BS_OEMName: " << rf.BS_OEMName;qDebug() << "BPB_BytsPerSec: " << hex << rf.BPB_BytsPerSec;qDebug() << "BPB_SecPerClus: " << hex << rf.BPB_SecPerClus;qDebug() << "BPB_RsvdSecCnt: " << hex << rf.BPB_RsvdSecCnt;qDebug() << "BPB_NumFATs: " << hex << rf.BPB_NumFATs;qDebug() << "BPB_RootEntCnt: " << hex << rf.BPB_RootEntCnt;qDebug() << "BPB_TotSec16: " << hex << rf.BPB_TotSec16;qDebug() << "BPB_Media: " << hex << rf.BPB_Media;qDebug() << "BPB_FATSz16: " << hex << rf.BPB_FATSz16;qDebug() << "BPB_SecPerTrk: " << hex << rf.BPB_SecPerTrk;qDebug() << "BPB_NumHeads: " << hex << rf.BPB_NumHeads;qDebug() << "BPB_HiddSec: " << hex << rf.BPB_HiddSec;qDebug() << "BPB_TotSec32: " << hex << rf.BPB_TotSec32;qDebug() << "BS_DrvNum: " << hex << rf.BS_DrvNum;qDebug() << "BS_Reserved1: " << hex << rf.BS_Reserved1;qDebug() << "BS_BootSig: " << hex << rf.BS_BootSig;qDebug() << "BS_VolID: " << hex << rf.BS_VolID;qDebug() << "BS_VolLab: " << rf.BS_VolLab;qDebug() << "BS_FileSysType: " << rf.BS_FileSysType;file.seek(510);uchar b510 = 0;uchar b511 = 0;in.readRawData(reinterpret_cast<char*>(&b510), sizeof(b510));in.readRawData(reinterpret_cast<char*>(&b511), sizeof(b511));qDebug() << "Byte 510: " << hex << b510;qDebug() << "Byte 511: " << hex << b511;}file.close();
}// 返回第i个目录项
RootEntry FindRootEntry(Fat12Header& rf, QString p, int i)
{RootEntry ret = {{0}};QFile file(p);// BPB_RootEntCnt:目录项个数if( file.open(QIODevice::ReadOnly) && (0 <= i) && (i < rf.BPB_RootEntCnt) ){QDataStream in(&file);// 定位到第i个目录项file.seek(19 * rf.BPB_BytsPerSec + i * sizeof(RootEntry));in.readRawData(reinterpret_cast<char*>(&ret), sizeof(ret));}file.close();return ret;
}// 根据文件名查找目录项
RootEntry FindRootEntry(Fat12Header& rf, QString p, QString fn)
{RootEntry ret = {{0}};for(int i=0; i<rf.BPB_RootEntCnt; i++){RootEntry re = FindRootEntry(rf, p, i);if( re.DIR_Name[0] != '\0' ){int d = fn.lastIndexOf(".");QString name = QString(re.DIR_Name).trimmed();if( d >= 0 ){QString n = fn.mid(0, d);QString p = fn.mid(d + 1);if( name.startsWith(n) && name.endsWith(p) ){ret = re;break;}}else{if( fn == name ){ret = re;break;}}}}return ret;
}void PrintRootEntry(Fat12Header& rf, QString p)
{for(int i=0; i<rf.BPB_RootEntCnt; i++){RootEntry re = FindRootEntry(rf, p, i);if( re.DIR_Name[0] != '\0' ){qDebug() << i << ":";qDebug() << "DIR_Name: " << hex << re.DIR_Name;qDebug() << "DIR_Attr: " << hex << re.DIR_Attr;qDebug() << "DIR_WrtDate: " << hex << re.DIR_WrtDate;qDebug() << "DIR_WrtTime: " << hex << re.DIR_WrtTime;qDebug() << "DIR_FstClus: " << hex << re.DIR_FstClus;qDebug() << "DIR_FileSize: " << hex << re.DIR_FileSize;}}
}int main(int argc, char *argv[])
{QCoreApplication a(argc, argv);QString img = "E:\\data.img";Fat12Header f12;qDebug() << "Read Header:";PrintHeader(f12, img);qDebug() << endl;qDebug() << "Print Root Entry:";PrintRootEntry(f12, img);qDebug() << endl;RootEntry r = FindRootEntry(f12, img, "LOADER.TXT");qDebug() << "DIR_Name: " << hex << r.DIR_Name;qDebug() << "DIR_Attr: " << hex << r.DIR_Attr;qDebug() << "DIR_WrtDate: " << hex << r.DIR_WrtDate;qDebug() << "DIR_WrtTime: " << hex << r.DIR_WrtTime;qDebug() << "DIR_FstClus: " << hex << r.DIR_FstClus;qDebug() << "DIR_FileSize: " << hex << r.DIR_FileSize;return a.exec();
}

对于多出来的目录项不必理会

文件以簇为单位存储,Fat12文件系统1簇等于1扇区,那么一个文件大于512字节如何存储?


4、读取目标文件到内存

实验:加载FAT12中的文件数据

- 步骤:

(1)在根目录区查找目标文件对应的项

(2)获取目标文件的起始簇号和文件大小

(3)根据FAT表中记录的逻辑先后关系读取数据

小贴士

- FAT表中的每个表项只占用12比特(1.5字节)

- FAT表一共记录了BPB_BytsPerSec * 9 * 2 / 3个表项 (9个扇区 * 512 /1.5)

- 可以使用一个short表示一个表项的值

- 如果表项值大于等于0xFF8,则说明已经到达最后一个簇

- 如果表项值等于0xFF7,则说明当前簇已经损坏

- 数据区起始簇(扇区)号为33,地址为0x4200(33 * 512)

- 数据区起始地址所对应的编号为2(不为0)(有了起始地址,这里可以用偏移地址)

- 因此,DIR_FstClus对应的地址为:0×4200+(DIR_FstClus-2)*512

编程实验

读取指定文件内容

#include <QtCore/QCoreApplication>
#include <QFile>
#include <QDataStream>
#include <QDebug>
#include <QVector>
#include <QByteArray>#pragma pack(push)
#pragma pack(1)struct Fat12Header
{char BS_OEMName[8];ushort BPB_BytsPerSec;uchar BPB_SecPerClus;ushort BPB_RsvdSecCnt;uchar BPB_NumFATs;ushort BPB_RootEntCnt;ushort BPB_TotSec16;uchar BPB_Media;ushort BPB_FATSz16;ushort BPB_SecPerTrk;ushort BPB_NumHeads;uint BPB_HiddSec;uint BPB_TotSec32;uchar BS_DrvNum;uchar BS_Reserved1;uchar BS_BootSig;uint BS_VolID;char BS_VolLab[11];char BS_FileSysType[8];
};struct RootEntry
{char DIR_Name[11];uchar DIR_Attr;uchar reserve[10];ushort DIR_WrtTime;ushort DIR_WrtDate;ushort DIR_FstClus;uint DIR_FileSize;
};#pragma pack(pop)void PrintHeader(Fat12Header& rf, QString p)
{QFile file(p);if( file.open(QIODevice::ReadOnly) ){QDataStream in(&file);file.seek(3);in.readRawData(reinterpret_cast<char*>(&rf), sizeof(rf));rf.BS_OEMName[7] = 0;rf.BS_VolLab[10] = 0;rf.BS_FileSysType[7] = 0;qDebug() << "BS_OEMName: " << rf.BS_OEMName;qDebug() << "BPB_BytsPerSec: " << hex << rf.BPB_BytsPerSec;qDebug() << "BPB_SecPerClus: " << hex << rf.BPB_SecPerClus;qDebug() << "BPB_RsvdSecCnt: " << hex << rf.BPB_RsvdSecCnt;qDebug() << "BPB_NumFATs: " << hex << rf.BPB_NumFATs;qDebug() << "BPB_RootEntCnt: " << hex << rf.BPB_RootEntCnt;qDebug() << "BPB_TotSec16: " << hex << rf.BPB_TotSec16;qDebug() << "BPB_Media: " << hex << rf.BPB_Media;qDebug() << "BPB_FATSz16: " << hex << rf.BPB_FATSz16;qDebug() << "BPB_SecPerTrk: " << hex << rf.BPB_SecPerTrk;qDebug() << "BPB_NumHeads: " << hex << rf.BPB_NumHeads;qDebug() << "BPB_HiddSec: " << hex << rf.BPB_HiddSec;qDebug() << "BPB_TotSec32: " << hex << rf.BPB_TotSec32;qDebug() << "BS_DrvNum: " << hex << rf.BS_DrvNum;qDebug() << "BS_Reserved1: " << hex << rf.BS_Reserved1;qDebug() << "BS_BootSig: " << hex << rf.BS_BootSig;qDebug() << "BS_VolID: " << hex << rf.BS_VolID;qDebug() << "BS_VolLab: " << rf.BS_VolLab;qDebug() << "BS_FileSysType: " << rf.BS_FileSysType;file.seek(510);uchar b510 = 0;uchar b511 = 0;in.readRawData(reinterpret_cast<char*>(&b510), sizeof(b510));in.readRawData(reinterpret_cast<char*>(&b511), sizeof(b511));qDebug() << "Byte 510: " << hex << b510;qDebug() << "Byte 511: " << hex << b511;}file.close();
}RootEntry FindRootEntry(Fat12Header& rf, QString p, int i)
{RootEntry ret = {{0}};QFile file(p);if( file.open(QIODevice::ReadOnly) && (0 <= i) && (i < rf.BPB_RootEntCnt) ){QDataStream in(&file);file.seek(19 * rf.BPB_BytsPerSec + i * sizeof(RootEntry));in.readRawData(reinterpret_cast<char*>(&ret), sizeof(ret));}file.close();return ret;
}// 根据文件名找到对应目录项
RootEntry FindRootEntry(Fat12Header& rf, QString p, QString fn)
{RootEntry ret = {{0}};for(int i=0; i<rf.BPB_RootEntCnt; i++){RootEntry re = FindRootEntry(rf, p, i);if( re.DIR_Name[0] != '\0' ){int d = fn.lastIndexOf(".");QString name = QString(re.DIR_Name).trimmed();if( d >= 0 ){QString n = fn.mid(0, d);QString p = fn.mid(d + 1);if( name.startsWith(n) && name.endsWith(p) ){ret = re;break;}}else{if( fn == name ){ret = re;break;}}}}return ret;
}// 打印存在的目录项各属性
void PrintRootEntry(Fat12Header& rf, QString p)
{for(int i=0; i<rf.BPB_RootEntCnt; i++){RootEntry re = FindRootEntry(rf, p, i);if( re.DIR_Name[0] != '\0' ){qDebug() << i << ":";qDebug() << "DIR_Name: " << hex << re.DIR_Name;qDebug() << "DIR_Attr: " << hex << re.DIR_Attr;qDebug() << "DIR_WrtDate: " << hex << re.DIR_WrtDate;qDebug() << "DIR_WrtTime: " << hex << re.DIR_WrtTime;qDebug() << "DIR_FstClus: " << hex << re.DIR_FstClus;qDebug() << "DIR_FileSize: " << hex << re.DIR_FileSize;}}
}// 返回FAT表所有表项
QVector<ushort> ReadFat(Fat12Header& rf, QString p)
{QFile file(p);// FAT表大小int size = rf.BPB_BytsPerSec * 9;uchar* fat = new uchar[size];QVector<ushort> ret(size * 2 / 3, 0xFFFF); // FAT表项个数和默认值if( file.open(QIODevice::ReadOnly) ){QDataStream in(&file);// 定位到FAT表的起始位置(主引导区后面的扇区)file.seek(rf.BPB_BytsPerSec * 1);in.readRawData(reinterpret_cast<char*>(fat), size);for(int i=0, j=0; i<size; i+=3, j+=2){ret[j] = static_cast<ushort>((fat[i+1] & 0x0F) << 8) | fat[i];ret[j+1] = static_cast<ushort>(fat[i+2] << 4) | ((fat[i+1] >> 4) & 0x0F);}}file.close();delete[] fat;return ret;
}// 读取指定文件名的内容
QByteArray ReadFileContent(Fat12Header& rf, QString p, QString fn)
{QByteArray ret;RootEntry re = FindRootEntry(rf, p, fn);if( re.DIR_Name[0] != '\0' ){QVector<ushort> vec = ReadFat(rf, p);QFile file(p);if( file.open(QIODevice::ReadOnly) ){char buf[512] = {0};QDataStream in(&file);int count = 0;ret.resize(re.DIR_FileSize);for(int i=0, j=re.DIR_FstClus; j<0xFF7; i+=512, j=vec[j]){file.seek(rf.BPB_BytsPerSec * (33 + j - 2));in.readRawData(buf, sizeof(buf));for(uint k=0; k<sizeof(buf); k++){if( count < ret.size() ){ret[i+k] = buf[k];count++;}}}}file.close();}return ret;
}int main(int argc, char *argv[])
{QCoreApplication a(argc, argv);QString img = "E:\\data.img";Fat12Header f12;qDebug() << "Read Header:";PrintHeader(f12, img);qDebug() << endl;qDebug() << "Print Root Entry:";PrintRootEntry(f12, img);qDebug() << endl;qDebug() << "Print File Content:";QString content = QString(ReadFileContent(f12, img, "LOADER.TXT"));qDebug() << content;return a.exec();
}

3、小结

加载新程序需要依赖于文件系统

FAT12是一种早期用于软盘的简单文件系统

FAT12文件系统的重要信息存储于0扇区

FAT12根目录区记录了文件的起始簇号和长度

通过查找根目录区能够确定是否存在目标文件

FAT12文件数据的组织使用了单链表的思想

- 文件数据离散的分布于存储介质中

- 文件数据通过FAT项进行关联

详解FAT12文件系统相关推荐

  1. ROS入门笔记(七):详解ROS文件系统

    ROS入门笔记(七):详解ROS文件系统 文章目录 01 Catkin编译系统 1.1 Catkin特点 1.2 Catkin工作原理 1.3 使用`catkin_make`进行编译 02 Catki ...

  2. 详解NTFS文件系统

    上篇在详解FAT32文件系统中介绍了FAT32文件系统存储数据的原理,这篇就来介绍下NTFS文件系统.NTFS,用过的的Windows系统的人都知道,它是一个很强大的文件系统,支持的功能很多,存储的原 ...

  3. 详解GPFS文件系统架构、组网和Building Block

    IBM GPFS(General Parallel FileSystem)是一个分布式.共享.并行集群文件系统,支持从多个节点同时对单一文件系统或一组文件系统的访问.GPFS可以在AIX.Linux和 ...

  4. 详解Linux文件系统

    文章目录 思维导图下载: 磁盘组成与分区 磁盘的组成: 为啥要进行格式化 FHS文件系统层级标准 ext文件系统结构 ext文件系统与目录的关系 术语 ext系列文件系统的区别 ext文件系统 ext ...

  5. 赠书| 详解GPFS文件系统架构、组网和Building Block

    此次技术干货分享内容分为GPFS技术实践分享和赠书活动2部分,对技术不太感兴趣的读者可以直接跳到赠书活动部分. 第一部分.GPFS技术实践分享 IBM GPFS(General Parallel Fi ...

  6. 详解GPFS文件系统架构、组网和Building Block。

    IBM GPFS(General Parallel FileSystem)是一个分布式.共享.并行集群文件系统,支持从多个节点同时对单一文件系统或一组文件系统的访问.GPFS可以在AIX.Linux和 ...

  7. 32 块大小_详解Linux文件系统的完整结构--引导块、超级块、GDT等

    概述 今天主要介绍一下Linux系统的文件系统,一起来看看吧~ 文件系统组成 网上看到的一张完整的文件系统图,如下: 首先,该图中有Boot Block.Super Block.GDT.Reserve ...

  8. linux 文件系统cache,终于找到一篇详解Linux文件系统Cache的文章

    级别: 初级 2006 年 5 月 11 日 文件 Cache 管理是 Linux 内核中一个很重要并且较难理解的组成部分.本文详细介绍了 Linux 内核中文件 Cache 管理的各个方面,希望能够 ...

  9. initramfs详解----设备文件系统

    initramfs的重要作用之一就是允许内核将保存根文件系统的存储设备的驱动不再编译进内核.本文我们就将硬盘驱动编译为模块,然后去识别硬盘设备.说道驱动,那么驱动一定是外部硬件设备的驱动,所以在介绍驱 ...

  10. Dooker镜像详解,文件系统分层,本地镜像的发布 (阿里云和私有库)commit (安装vim ),详细演示

    目录 1.镜像 1.1分层的镜像 1.2UnionFS(联合文件系统) 1.3Docker镜像加载原理 1.4为什么 Docker 镜像要采用这种分层结构呢 2.Docker镜像commit操作案例 ...

最新文章

  1. 【部署类】专题:消息队列MQ、进程守护Supervisor
  2. linux学习笔记四:安装lsusb
  3. 保存图像_设计干货知识:SVG vs PNG vs JPG|图像格式的优缺点
  4. 内存和外存的主要区别_内存与外存的关键区别有哪些?
  5. 如何添加java环境变量_如何配置java环境变量
  6. 山西最值得一去的5座古镇,你都去过吗?
  7. npumpy.insert(arr, obj, values[, axis])
  8. Redis 基本数据类型
  9. 做了MVC模式一年,可不要把传统模式忘记呀!ashx配合aspx实现AJAX加载JSON数据...
  10. LabVIEW在快速传输速率下丢失UDP数据包
  11. 计算机课程用到的软件,在电脑上录课用什么软件好?好用的录课软件推荐
  12. 华为云计算IE面试笔记-Fusionsphere架构及组件介绍(服务器虚拟化解决方案)
  13. 启动windows的mysql_MySQL的启动方法(windows 平台)
  14. 编写bootstrap响应式页面 就这么简单
  15. 系统辨识(六):最小二乘法的修正算法
  16. UE4摄像机系统解析
  17. [机器学习][基础编程][pandas]pandas基本操作
  18. 高楼之下,尸骨为基:移动互联网的七宗败案
  19. mybatis配置mybatis.configuration.map-underscore-to-camel-case=true
  20. 每日词根——her/heir/herit

热门文章

  1. Nginx+php+mysql超时问题总结
  2. 如何导出带有dn值的栅格影像(方便arcgis处理)
  3. php 睡眠,win10系统睡眠和休眠有什么区别
  4. 新浪2010南非足球世界杯漂亮表格的制作
  5. Docker命令(二)
  6. 李大潜院士:学习数学是战略性投资
  7. 为什么建网站需要服务器,建网站需不需要服务器
  8. java代码计算两个时间相差的天数:
  9. Android开发打开手机自带浏览器
  10. 马氏距离(Mahalanobis Distance)与欧式距离