自制操作系统流程笔记(二)

笔记一主要记录了保护模式的知识,笔记二将从os进入保护模式开始。

1.FAT12文件系统

参考:https://blog.csdn.net/sunpuyizu19/article/details/50667686

   http://blog.sina.com.cn/s/blog_3edcf6b80100crz1.html

     https://blog.csdn.net/yangyang031213/article/details/79030247

 使用diskgenius模拟软盘文件做实验。

FAT12是Microsoft公司DOS操作系统所支持的文件系统之一,此外还有FAT16和FAT32,之后会分别详述这些文件系统。

当软盘被标准格式化后,磁盘被格式化为:每磁头80个柱面(磁道),每个柱面有18个扇区,每个扇区有512字节空间。所以标准软盘的总空间(容量)为:

2*80*18*512=1474560B=1440K=1.44M

每个扇区512字节。

1.1引导扇区

操作系统标识FAT12文件系统是因为在逻辑0扇区(即引导扇区)处还存储着一个特定的数据结构,此结构有固定的格式,在操作系统将此磁盘格式化时自动生成,具体数据结构如下表所示:

偏移13处的是每簇所占用的扇区,类型是字节,簇是数据存储的最小单位,此字段的值取决于分区的大小,在FAT12格式下一般为1,即每簇只有1个扇区(512字节),簇越大,那么分区的容量也就越大,通过增加簇的扇区数,可以支持更大的磁盘分区,标准的簇大小为1、2、4、8、16、32、64和128,FAT12格式下只能管理2^12个簇(4096),所以在FAT12格式下能管理和分配的最大空间为:4096*1*512=2097152B=2M,所以FAT12一般只适合3.5寸高密度软盘(1.44M)。

1.2 文件目录表(分配表)

文件分配表所在的扇区应该是(隐藏扇区+保留扇区)=0+1=第1扇区处,从第1扇区开起到第9扇区结束,第一个文件分配表共占用9个扇区,第二个文件分配表从第10个扇区开始到第18扇区结束,在引导扇区的数据结构中明明确的指出了这些位置。

    文件分配表数据结构如下图所示:

  

在FAT表开始扇区的第1字节是存储介质,0f0h代表软盘,0f8代表硬盘;第2、3这两个字节都是0ffh,代表了FAT文件分配表标识符,从第四个字节开始与用户数据区所有的簇一一对应,应该注意的是,用户数据区的第一个簇的序号是002,而不是000,因为储存介质和标识符占用了这两个序号。

    在FAT12格式中用12比特位来代表一个簇的序号,我们知道,每个字节有8位比特,所以每个簇要占用1.5个字节,也就是说,占用了第1字节和第2字节的一半才能表示一个簇的序号,半字节的拆分办法按照下图的方式进行:

最终我们得到了这4个簇号的内容,内容是0ff0-0ff7h代表坏簇,磁道或柱面损坏不可使用,在格式式磁盘时由系统自动填充;内容是0ff8-0fffh代表文件内容结束,到此簇为止;其它的值代表着下一个簇号,接着我们分析一下刚才得到的那4个簇号的内容代表的意义,第2簇号的内容是0fffh,代表这个文件只占用了第2簇,文件的大小在512B(每簇1扇区512字节)之内。第3簇号的内容是004h,代表它的下一个簇是第4簇;第4簇号的内容是005h,代表它的下一个簇是第5簇,第5簇号的内容是0fffh,代表文件内容结束,所以这个文件应该是从第3簇开始到第5簇结束,占据了3簇的空间,文件大小在1536B(每簇1扇区512字节)之内。

1.3 文件目录项

文件目录项最开始位于扇区19(隐藏隐藏+保留扇区+FAT文件分配表占用扇区=0+1+9+9)处,它一共占用了14个扇区的空间,在引导扇区的数据结构中偏移17处的字段BPB_RootEntCnt指出了最大根目录数,在FAT12中的默认值是224,每个文件目录项占用了32字节的空间,那么共占用224*32/512=14扇区。

    文件目录项的32字节数据结构如下图所示:

    位于偏移11处的是文件属性,使用比特位来设置值:

    00000000:普通文件,可随意读写

    00000001:只读文件,不可改写

    00000010:隐藏文件,浏览文件时隐藏列表

    00000100:系统文件,删除的时候会有提示

    00001000:卷标,作为磁盘的卷标识符

    00010000:目录文件,此文件是一个子目录,它的内容就是此目录下的所有文件目录项

    00100000:归档文件

    文件的属性可以叠加使用,可以具有多重属性,即设置为只读的时候也可以同时隐藏。

    偏移12处的共10字节长的内容没有使用,保留。

    偏移22处的是双字节长的文件最后修改时间,使用的方式是分位压缩存储方式,两个字节共16位从高到低分别存储时分秒的数值,其中时占用5位(11-15),值从0-23,代表小时;分占用6位(5-10),值从0-59,代表分钟;秒占用5位(0-4),值为0-29,它的倍数(值*2)就得到秒数。

    偏移24处的是双字节长的文件最后修改日期,使用的方式是分位压缩存储方式,两个字节共16位从高到低分别存储年月日的数值,其中年占用7位(9-15),值从0-199,此值加上1980就可以得到年份,代表从1980到2099年;月占用4位(5-8),值从1-12,代表月份;日占用5位(0-4),值从1-31,代表当月天数。

    位于偏移26处的是双字节长的文件首簇号,利用此值就可以得到文件内容占用的第一个簇,然后在文件分配表中就可以得到所有的文件簇了。文件分配表中第一个簇号为002,即文件目录项结束后的第一个簇(扇区,若每簇扇区为数为1)。

    最后位于偏移28处的双字(4B)长的文件长度(字节)值。

每个文件目录项的长度是32字节,偏移0处的8字节长的文件名,必须是大写的ASCII字符串,不足8字节就以空格(20h)来填充,接着是3字节长的文件后缀名,同样是大写的ASCII字符串,不足3字节以空格填充。如果文件名的第1字节是0E5h表示此文件已经删除,第1字节是0表示此目录项可用。

2. ELF文件格式解析

参考:https://blog.csdn.net/dddxxxx/article/details/80347610

2.1 ELF文件概览

首先,ELF文件格式提供了两种视图,分别是链接视图和执行视图。

链接视图是以节(section)为单位,执行视图是以段(segment)为单位。链接视图就是在链接时用到的视图,而执行视图则是在执行时用到的视图。上图左侧的视角是从链接来看的,右侧的视角是执行来看的。总个文件可以分为四个部分:

  • - ELF header: 描述整个文件的组织。
  • - Program Header Table: 描述文件中的各种segments,用来告诉系统如何创建进程映像的。
  • - sections 或者 segments:segments是从运行的角度来描述elf文件,sections是从链接的角度来描述elf文件,也就是说,在链接阶段,我们可以忽略program header table来处理此文件,在运行阶段可以忽略section header table来处理此程序(所以很多加固手段删除了section header table)。从图中我们也可以看出,segments与sections是包含的关系,一个segment包含若干个section。
  • - Section Header Table: 包含了文件各个segction的属性信息,我们都将结合例子来解释。

程序头部表(Program Header Table),如果存在的话,告诉系统如何创建进程映像。
节区头部表(Section Header Table)包含了描述文件节区的信息,比如大小、偏移等。

2.2 ELF header

elf header 结构体:

    #define EI_NIDENT 16
    typedef struct {
           unsigned char e_ident[EI_NIDENT];
           ELF32_Half e_type;  文件类型
           ELF32_Half e_machine;  机器的体系结构
           ELF32_Word e_version;  文件版本
           ELF32__Addr e_entry;  程序入口地址
           ELF32_Off e_phoff;  程序头部表在文件中的偏移量
           ELF32_Off e_shoff;  节区头部表在文件中的偏移量
           ELF32_Word e_flags;  
           ELF32_Half e_ehsize;  ELF header 大小
           ELF32_Half e_phentsize;  Programma header table 中每一个条目的大小
           ELF32_Half e_phnum;  Programma header table中有多少个条目
           ELF32_Half e_shentsize;  Section header table 中每个条目的大小
           ELF32_Half e_shnum;  Section header table中有多少条目
           ELF32_Half e_shstrndx;  包含节名称的字符串表示第几个节
    }Elf32_Ehdr;

常用数据格式:

2.3 Programma header table 数据结构

描述的是段在文件中的位置、大小以及它被放进内存后所在的位置和大小

p_type   当前Programma header所描述的段的类型

p_offset  段的第一个字节在文件中的偏移

p_vaddr  段的第一个字节在内存中的虚拟地址

p_paddr  在物理地址地位相关系统中,此项是为物理地址保留

p_filesz   段在文件中的长度

p_memsz   段在内存中的长度

p_flags  与段相关的标志

p_align  根据此项值来确定段在文件以及内存中如何对齐

原文地址:https://www.cnblogs.com/x-police/p/10797737.html