主页 | 文件 | 属性 | 概念 | 词汇

# 文件 - $LogFile (2)

前一页 后一页

## 概述

## 属性

类型 | 描述 | 名称
--- | --- | ---
0x10 | 标准信息文件 （$STANDARD_INFORMATION） |
0x30 | 文件名文件 （$FILE_NAME） | $LogFile
0x80 | 数据文件 （$DATA） | [未命名]

## 文件结构

### 未命名数据流

对日志文件了解很少

## 注意

### 其他信息

日志区域是由一个4KB的日志记录序列组成的，每个日志记录结构如下：

        偏移(长度)        内容
        0(4)             幻数 'RCRD'
        1E(12)           修正或固定

按照推测，日志记录包含一序列不同大小的记录，它们的结构不清楚。文件2是$LogFile，它包含处理事务的 记录以保证在系统瘫痪的时候数据的完整性。如37页提到的，它由2个重新启动区的拷贝和无限的日志区组成。

如果要把一个文件写到一个存储单元上，你必须修正这个文件本身以添加此文件系统的一些表格（例如文件 数据）。在此，你要经过两个操作步骤（修正文件自身，修正文件数据）。

如果此项任务完成，可以确认文件被写到存储单元上，并且文件系统处于定义的状态。

如果不能完成此项任务（例如如果系统瘫痪或日常的系统故障），则文件系统处于未定义状态。把它恢复到 定义（规定）状态的唯一途径（此操作称为“击退”）是把它放进一个特殊文件里，日志文件，那么就成功完成了 对此项任务的操作。

在系统故障后第一次进入磁盘时，系统读取日志文件并“击退”最近一项任务开端的所有操作。

- 当系统写向日志文件时，此项操作必须是自动且立即的。
- 你可以在很短的时间内把卷恢复回规定状态，恢复时间与磁盘大小无关，只与失败任务的复杂程度有关。

  注意：此项操作不是由WINDOWS NT的chkdsk执行的，而是由系统执行的：此项标准可靠的操作功能是NTFS的特点。

- 如果你的硬件可靠，因为它的存在可确保你进入卷的所有文件的权限。但是不能恢复最终的数据丢失。

        日志文件结构：
        两个重新启动区分布在最初的两页（重新启动页），如果卷没有被布置过，它们是一致的。

        然后是日志记录。它以一个记录标题开头，接着是日志文件大小。当卷被第一次格式化时不
        是所有的页面都包含日志记录，而是卷龄，所有的记录都会在用。当日志文件填充满时，处
        于开始位置的记录就会被清除（大概是通过修改the oldest_lsn），并且在文件开端开始写
        入。从而，此日志文件看起来象是一个循环体。

        日志文件的重新启动页标题（开始重新启动区）

        struct {
                NTFS_RECORD;                特征码是“RSTR”
                __u64 chkdsk_lsn;           对于此重新启动页的检测磁盘的日志文序列号 。
                                            只有当特征码转到"CHKD". = 0时才用到它。

                __u32 system_page_size;     统页的比特大小，必须 >= 512，而且是2的n次幂。
                                            可以用它来计算需要用的空间大小，并把它加到
                                            NTFS的ntfs.usa_offset里。然后验证结果
                                            小于restart_offset. = 0x1000。

                __u32 log_page_size;        志文件记录的大小，必须>= 512，并且是2的n次幂。
                                            = 0x1000

                __u16 restart_offset;       从记录开始到重新启动记录的偏移比特。
                                            此值必须被排列为8比特边界 = 0x30

                __s16 minor_ver;            日志文件的低版本，如果低版本是1，只能检测。
                                            （>=1同样对待，<=0也行）

                __u16 major_ver;            日志文件的主流版本（＝1但是＝0是好的）

        }  RESTART_PAGE_HEADER;

        日志文件重新启动区记录。把RESTART_PAGE_HEADER的偏移（位置）和restart偏移（位置）相加即可得
        到此记录的偏移值（位置）。

        struct {
                __u64 current_lsn;          日志文件记录。= 0x700000, 0x700808

                __u16 log_clients;          紧跟在重新启动区后面的日志客户记录号＝1

                __u16 client_free_list;     多少客户是空闲的（？）如果 != 0xffff,
                                            检查log_clients > client_free_list.
                                            = 0xffff

                __u16 client_in_use_list;   多少客户在用（？）如果 != 0xffff
                                            检查log_clients > client_in_use_list.
                                            = 0

                __u16 flags;                ??? = 0

                __u32 seq_number_bits;      ??? = 0x2c or 0x2d

                __u16 restart_area_length;  重新启动区的长度。如果版本匹配需要进一步检查。
                                            否则就略过。restart_offset +restart_area_length
                                            必须 <= system_page_size. 而且restart_area_length
                                            必须 >= client_array_offset +(log_clients * 0xa0)
                                            = 0xd0

                __u16 client_array_offset;  在版本匹配的情况下从此记录开始到第一个客户记录的
                                            偏移量。否则此偏移量假定为(sizeof(RESTART_AREA) + 7) & ~7
                                            例如，上舍入第一个8比特边界。
                                            用任一种方法到客户队列的偏移量都必须排列为一个8比
                                            特边界。同样，重新启动页的偏移量＋到客户队列的偏移量
                                            必须<= 510. 到客户队列的偏移量＋(log_clients * 0xa0)
                                            必须<= SystemPageSize
                                            = 0x30

                __u64 file_size;            日志文件的比特大小。如果
                                            重新启动的偏移量＋文件大小的偏移量>510
                                            就会出错。当以重新启动区开始的时候这是最初的一个检
                                            查，看起来好像是失败了，其实这仅仅意味着上述一些数
                                            值将被多部转移保护所破坏。
                                            如果这个结构被解除保护那么这些检查将是无效过程。
                                            计算此文件大小的位数并检查
                                            seq_number_bits == 0x43 - file_size bits
                                            = 0x400000

                __u32 last_lsn_data_length; ??? = 0, 0x40

                __u16 record_length;        此记录的字节大小。如果版本匹配，
                                            此记录长度的值是8的倍数，例如：
                                            (record_length + 7) & ~7 == record_length.
                                            = 0x30

                __u16 log_page_data_offset; ??? = 0x40

        }  RESTART_AREA;

        日志文件客户记录。起始于0x58即使有上述意外发生它也会在0x60开始. /-:

        struct {
                __u64 oldest_lsn;           此客户记录的最古老日志文件的序列号
                                            = 0xbd16951d

                __u64 client_restart_lsn;   ??? = 0x700000, 0x700827, 0x700d07

                __u16 prev_client;          ??? = 0x808, 0xd07, 0xd5d

                __u16 next_client;          ??? = 0x70

                __u16 seq_number;           ??? = 0, 4 大小不确定。称为“卷清除标记”，大小为一个字节。

                __u16 client_name;          ??? = 空字串??? 大小不确定

        }  RESTART_CLIENT;

        注意：上述客户记录是在0xffffffff之后的，可能指示重新启动区的结尾。

        那么这有8字节＝0，one __u32 = 8,然后是标准编码字串“NTFS”,然后调零直至页尾？

        日志页记录页标题。每一个日志页以标题开始，然后是几个日志记录结构。

        struct {
                NTFS_RECORD;                        幻数"RCRD".
                union {
                        __u64 last_lsn;
                        __u32 file_offset;
                }  copy;
                __u32 flags;
                __u16 page_count;
                __u16 page_position;
                union {
                        struct {
                                __u64 next_record_offset;
                                __u64 last_end_lsn;
                        }  packed;
                }  header;
        }  RECORD_PAGE_HEADER;

        日志记录可能有的标记

        enum {
                LOG_RECORD_MULTI_PAGE = 1,        ???
                LOG_RECORD_SIZE_PLACE_HOLDER = 0xffff,
                               无法使用日志记录，gcc此标记为16比特
        }  LOG_RECORD_FLAGS;

        日志记录头

        struct {
                __u64 this_lsn;
                __u64 client_previous_lsn;
                __u64 client_undo_next_lsn;
                __u32 client_data_length;
                struct {
                        __u16 seq_number;
                        __u16 client_index;
                }  client_id;
                __u32 record_type;
                __u32 transaction_id;
                LOG_RECORD_FLAGS flags;
                __u16 reserved_or_alignment[3];
        现在在结构中的偏移量为0x30
                __u16 redo_operation;
                __u16 undo_operation;
                __u16 redo_offset;
                __u16 redo_length;
                __u16 undo_offset;
                __u16 undo_length;
                __u16 target_attribute;
                __u16 lcns_to_follow;              Number of lcn_list entries following this entry.
                __u16 record_offset;
                __u16 attribute_offset;
                __u32 alignment_or_reserved;
                __u32 target_vcn;
                __u32 alignment_or_reserved1;
                struct {                           Only present if lcns_to_follow is not 0.
                        __u32 lcn;
                        __u32 alignment_or_reserved;
                }  lcn_list[0];
        }  LOG_RECORD;

        重新启动区有一个指针到日志区，比如第一个和最后一个写入的日志记录以及最后一个写入的检查
        点记录。如果重新启动区出现问题，恢复起来将十分困难--因此要有两个重新启动区的拷贝。

        单独的日志记录用逻辑序列号(LSNs)识别.虽然日志区被层层包围，但(LSNs)不是，所以它们被用以
        代替日志文件中的偏移量来识别日志记录。

        任何有关元数据的修改（比如更新文件系统打开的时间标签）将导致日志文件动作，继而会导致重
        新启动区变化。这些有害比特一般是隐藏的：如果最后的日志记录表明没有未完的任务那么文件系
        统就是干净的。

Online 中文在线 Validate HTML Validate CSS $Id: logfile.html,v 1.11 2001/07/11 16:31:45 flatcap Exp $