系列文章目录
文章目录
- 系列文章目录
- 在 ReactOs 内核中
- ROS_SECTION_OBJECT结构体
- MM_SECTION_SEGMENT结构体
- SECTION_PAGE_DIRECTORY结构体
- SECTION_PAGE_TABLE结构体
在 ReactOs 内核中
在 ReactOs 内核中,映射区的数据结构是 ROS_SECTION_OBJECT,显然这与 Windows中的“正定义有所不同,但是这并不妨碍我们对映射区的理解:
ROS_SECTION_OBJECT结构体
typedef struct _ROS_SECTION_OBJECT
{
CSHORT Type;
CSHORT Size;
LARGE_INTEGER MaximumSize;
ULONG SectionPageProtection; //页面保护模式
ULONG AllocationAttributes; //属性
PFILE_OBJECT FileObject; //指向文件对象
union
{
PMM_IMAGE_SECTION_OBJECT ImageSection; //如果是可指向影像文件
PMM_SECTION_SEGMENT Segment; //如果是数据文件
};
} ROS_SECTION_OBJECT, *PROS_SECTION_OBJECT;
映射区的数据结构中必须有指向目标文件对象的指针,这是不言而喻的。如果目标文件是可执行映像文件,那就要有个指针指向另一个数据结构,即MM_IMAGE_SECTION_OBJECT,在那里有个映射段结构指针的数组,还有个字段说明段的数量,因为可执行映像文件里面段的数量是不固定的。而如果目标文件是数据文件,则只有一个段,所以直接使这个指针指向一个映射段数据结构即 MM_SECTION_SEGMENT 就可以了。
再看映射段的数据结构MM_SECTION_SEGMENT :
MM_SECTION_SEGMENT结构体
typedef struct _MM_SECTION_SEGMENT
{
LONGLONG FileOffset; /* start offset into the file for image sections */
ULONG_PTR VirtualAddress; /* dtart offset into the address range for image sections */
ULONG RawLength; /* length of the segment which is part of the mapped file */
ULONG Length; /* absolute length of the segment */
ULONG Protection;
FAST_MUTEX Lock; /* lock which protects the page directory */
ULONG ReferenceCount;
SECTION_PAGE_DIRECTORY PageDirectory;
ULONG Flags;
ULONG Characteristics;
BOOLEAN WriteCopy;
} MM_SECTION_SEGMENT, *PMM_SECTION_SEGMENT;
字段FileOffset 说明本映射段的起点对应于文件内部的位移,对于数据文件显然应该是0。读者可以结合这里的注释与上面的代码搞清其余字段的意义和作用。这里要说明的是作为内部成分的映射段页面目录,即SECTION_PAGE_DIRECTORY数据结构PageDirectory。顾名思义,这是个页面目录,其数据结构为:
SECTION_PAGE_DIRECTORY结构体
typedef struct
{
PSECTION_PAGE_TABLE PageTables[NR_SECTION_PAGE_TABLES];
} SECTION_PAGE_DIRECTORY, *PSECTION_PAGE_DIRECTORY;
这是个指针数组,数组的大小NR_SECTION_PAGE_TABLES定义为1024,所以正好占一个页面。
每个指针指向一个映射段二级页面表,即SECTION_PAGE_TABLE 数据结构。
SECTION_PAGE_TABLE结构体
typedef struct
{
ULONG Entry[NR_SECTION_PAGE_ENTRIES];
} SECTION_PAGE_TABLE, *PSECTION_PAGE_TABLE;
这又是一个数组,数组的大小NR_SECTION_PAGE_ENTRIES也定义为1024,也占一个页面显然,映射段页面目录和映射段二级页面表构成了映射段的页面映射表,在形式上与内存的页面映射表一致。不过,只要目标文件不是太大,映射段页面目录中的大部分目录项都是NULL,因而二级映射表实际上不会占那么多的页面。
完成了这些操作之后,最后通过 CcRosReferenceCache()递增目标文件的BCB即“缓冲区控制块”的引用计数。
上面只是创建了(文件)映射区对象,而并未实际建立映射。实际的映射是通过另一个系统调用NMapViewOfSection()完成的,这个系统调用将一个映射区对象的一部分或全部映射到某个进程的用户空间,这个进程不必是当前进程。