吾爱破解 - 52pojie.cn

 找回密码
 注册[Register]

QQ登录

只需一步,快速开始

查看: 8525|回复: 0
收起左侧

[其他转载] NTFS文件系统之浅析$LogFile文件

  [复制链接]
swlings 发表于 2019-3-14 14:11
本帖最后由 swlings 于 2019-3-18 11:57 编辑

NTFS是一种日志事务型文件系统,其工作原理就不多说了,感兴趣的可以参考《深入解析windows操作系统》第四版的第12章,这篇重点在于解析$LogFile这个文件的数据结构。言归正传,那么为什么是“浅析”呢?因为不够深。。。咳咳咳,无意开车。。。
NTFS的日志记录分为两个组成部分,其中包含NTFS自身以及LFS日志文件系统。如果说NTFS是日志的作者,那么LFS就是执笔人,一个生产,一个记录。
$LogFile的主要功能就是做事务管理,用于保证NTFS的可恢复性,类似于数据库的事务管理。

$LogFile文件的大小一般为64M,但不固定,分区较小的情况下可能小于64M,在不同版本中$LogFile的组成略有不同,早期版本是2+n的形式,较新的是2+32+n的形式。
lfs-layout.png
第一个2表示的是文件的前2页,也叫重启动区域,第2个区域是最后一次更新的备份区域,用于最后一次更新发生错误时用于恢复的。
最后一块区域是循环日志区域,该区域是环形循环写入,类似于ringbuffer,用SequenceNumber记录循环次数。

日志记录空间分配用页计数,类似于文件系统的簇,页的大小一般为4096Bytes .

先来说说RestartPage,RestartPage占用了日志文件的第一页和第二页,其中第二页是第一页的备份(实际好像并不一样)。
暂时我只分析第一页,结构如下图:
RestartPage1.png


下面是部分源码,但这个是1.0版本(日志版本),在数据结构上和现在的2.0版本还是有些区别的。
[C++] 纯文本查看 复制代码
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
//
//  Log Restart Page Header.  This structure is at the head of the restart
//  areas in a log file.
//
 
typedef struct _LFS_RESTART_PAGE_HEADER {
 
    //
    //  Cache multisector protection header.
    //
 
    MULTI_SECTOR_HEADER MultiSectorHeader;
 
    //
    //  This is the last Lsn found by checkdisk for this volume.
    //
 
    LSN ChkDskLsn;
 
    //
    //  System page size.  This is the page size of the system which
    //  initialized the log file.  Unless the log file has been gracefully
    //  shutdown (there are no clients with restart areas), it is a fatal
    //  error to attempt to write to a log file on a system with a differen
    //  page size.
    //
 
    ULONG SystemPageSize;
 
    //
    //  Log Page Size.  This is the log page size used for this log file.
    //  The entire Lfs restart area must fit on a single log page.
    //
 
    ULONG LogPageSize;
 
    //
    //  Lfs restart area offset.  This is the offset from the start of this
    //  structure to the Lfs restart area.
    //
 
    USHORT RestartOffset;
 
    //
    //  The indicates major and minor versions.  Note that the pre-release versions
    //  have -1 in both positions.  Major version 0 indicates the transition
    //  from Beta to USA support.
    //
    //      Major Version
    //
    //          -1      Beta Version
    //           0      Transition
    //           1      Update sequence support.
    //
 
    SHORT MinorVersion;
    SHORT MajorVersion;
 
    //
    //  Update Sequence Array.  Used to protect the page block.
    //
 
    UPDATE_SEQUENCE_ARRAY UpdateSequenceArray;
 
} LFS_RESTART_PAGE_HEADER, *PLFS_RESTART_PAGE_HEADER;


我们从RestartPageHeader开始解释其中的结构以及各个成员变量的意义。
前面4个字节是标识 RSTR
紧接着就是更新序列数组的偏移和大小,占用4个字节,更新序列数组是用来确定每页的数据写入是否完整。
接着是ChkDskLsn,占用8个字节,这个是磁盘自检的时候才会用到。
接着是系统分页大小和日志分页大小,各占4个字节,值都是4096。
接着就是数据区的偏移量了,占用4个字节。
后面跟着日志系统的版本号,占用4个字节,高2个字节表示主版本号,低2个字节表示次版本号。
版本号后面跟着的就是更新序列数组了,其中前两个字节表示该页修改的次数,后面2 * 8个字节分别是该页的每个512字节的最后两个字节,而每个512字节的最后两个字节被最开始的两个字节(修改次数)替换,所以解析的时候需要还原回去。
[C++] 纯文本查看 复制代码
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
//
//  Lfs Restart Area.  Two copies of these will exist at the beginning of the
//  log file.
//
 
typedef struct _LFS_RESTART_AREA {
 
    //
    //  Current Lsn.  This is periodic snapshot of the current logical end of
    //  log file to facilitate restart.
    //
 
    LSN CurrentLsn;
 
    //
    //  Number of Clients.  This is the maximum number of clients supported
    //  for this log file.
    //
 
    USHORT LogClients;
 
    //
    //  The following are indexes into the client record arrays.  The client
    //  records are linked into two lists.  A free list of client records and
    //  an in-use list of records.
    //
 
    USHORT ClientFreeList;
    USHORT ClientInUseList;
 
    //
    //  Flag field.
    //
    //      RESTART_SINGLE_PAGE_IO      All log pages written 1 by 1
    //
 
    USHORT Flags;
 
    //
    //  The following is the number of bits to use for the sequence number.
    //
 
    ULONG SeqNumberBits;
 
    //
    //  Length of this restart area.
    //
 
    USHORT RestartAreaLength;
 
    //
    //  Offset from the start of this structure to the client array.
    //  Ignored in versions prior to 1.1
    //
 
    USHORT ClientArrayOffset;
 
    //
    //  Usable log file size.  We will stop sharing the value in the page header.
    //
 
    LONGLONG FileSize;
 
    //
    //  DataLength of last Lsn.  This doesn't include the length of
    //  the Lfs header.
    //
 
    ULONG LastLsnDataLength;
 
    //
    //  The following apply to log pages.  This is the log page data offset and
    //  the length of the log record header.  Ignored in versions prior to 1.1
    //
 
    USHORT RecordHeaderLength;
    USHORT LogPageDataOffset;
 
    //
    //  Client data.
    //
 
    LFS_CLIENT_RECORD LogClientArray[1];
 
} LFS_RESTART_AREA, *PLFS_RESTART_AREA;


[C++] 纯文本查看 复制代码
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
//
//  Log Client Record.  A log client record exists for each client user of
//  the log file.  One of these is in each Lfs restart area.
//
 
#define LFS_NO_CLIENT                           0xffff
#define LFS_CLIENT_NAME_MAX                     64
 
typedef struct _LFS_CLIENT_RECORD {
 
    //
    //  Oldest Lsn.  This is the oldest Lsn that this client requires to
    //  be in the log file.
    //
 
    LSN OldestLsn;
 
    //
    //  Client Restart Lsn.  This is the Lsn of the latest client restart
    //  area written to the disk.  A reserved Lsn will indicate that no
    //  restart area exists for this client.
    //
 
    LSN ClientRestartLsn;
 
    //
    //
    //  Previous/Next client area.  These are the indexes into an array of
    //  Log Client Records for the previous and next client records.
    //
 
    USHORT PrevClient;
    USHORT NextClient;
 
    //
    //  Sequence Number.  Incremented whenever this record is reused.  This
    //  will happen whenever a client opens (reopens) the log file and has
    //  no current restart area.
 
    USHORT SeqNumber;
 
    //
    //  Alignment field.
    //
 
    USHORT AlignWord;
 
    //
    //  Align the entire record.
    //
 
    ULONG AlignDWord;
 
    //
    //  The following fields are used to describe the client name.  A client
    //  name consists of at most 32 Unicode character (64 bytes).  The Log
    //  file service will treat client names as case sensitive.
    //
 
    ULONG ClientNameLength;
 
    WCHAR ClientName[LFS_CLIENT_NAME_MAX];
 
} LFS_CLIENT_RECORD, *PLFS_CLIENT_RECORD;


(太多了。。。未完待续)

发帖前要善用论坛搜索功能,那里可能会有你要找的答案或者已经有人发布过相同内容了,请勿重复发帖。

您需要登录后才可以回帖 登录 | 注册[Register]

本版积分规则

返回列表

RSS订阅|小黑屋|处罚记录|联系我们|吾爱破解 - LCG - LSG ( 京ICP备16042023号 | 京公网安备 11010502030087号 )

GMT+8, 2025-7-12 06:24

Powered by Discuz!

Copyright © 2001-2020, Tencent Cloud.

快速回复 返回顶部 返回列表