Windows NT FileSystem Internals》学习笔记之IO_STACK_LOCATION的结构

本文介绍了NTDDK中StackLocation结构体的关键字段及其作用,包括MajorFunction、MinorFunction、Flags等,并详细解释了这些字段如何帮助内核模式驱动处理IRP请求。

by fengcaho

NTDDK定义的Stack Location结构体由以下几个字段组成:

MajorFunction:

该字段定义了一个函数功能集,内核模式驱动可以实现其中的每一个函数。每一个函数由一个函数代码对应。

当内核模式驱动接收到一个IRP时,驱动首先检查当前StackLocation中的MajorFunction字段,得出驱动将要执行的功能,可能的MajorFunction功能代码如下:

#define IRP_MJ_CREATE                   0x00

#define IRP_MJ_CREATE_NAMED_PIPE        0x01

#define IRP_MJ_CLOSE                    0x02

#define IRP_MJ_READ                     0x03

#define IRP_MJ_WRITE                    0x04

#define IRP_MJ_QUERY_INFORMATION        0x05

#define IRP_MJ_SET_INFORMATION          0x06

#define IRP_MJ_QUERY_EA                 0x07

#define IRP_MJ_SET_EA                   0x08

#define IRP_MJ_FLUSH_BUFFERS            0x09

#define IRP_MJ_QUERY_VOLUME_INFORMATION 0x0a

#define IRP_MJ_SET_VOLUME_INFORMATION   0x0b

#define IRP_MJ_DIRECTORY_CONTROL        0x0c

#define IRP_MJ_FILE_SYSTEM_CONTROL      0x0d

#define IRP_MJ_DEVICE_CONTROL           0x0e

#define IRP_MJ_INTERNAL_DEVICE_CONTROL  0x0f

#define IRP_MJ_SHUTDOWN                 0x10

#define IRP_MJ_LOCK_CONTROL             0x11

#define IRP_MJ_CLEANUP                  0x12

#define IRP_MJ_CREATE_MAILSLOT          0x13

#define IRP_MJ_QUERY_SECURITY           0x14

#define IRP_MJ_SET_SECURITY             0x15

#define IRP_MJ_POWER                    0x16

#define IRP_MJ_SYSTEM_CONTROL           0x17

#define IRP_MJ_DEVICE_CHANGE            0x18

#define IRP_MJ_QUERY_QUOTA              0x19

#define IRP_MJ_SET_QUOTA                0x1a

#define IRP_MJ_PNP                      0x1b

#define IRP_MJ_PNP_POWER                IRP_MJ_PNP      // Obsolete....

#define IRP_MJ_MAXIMUM_FUNCTION         0x1b

MinorFunction

MinorFunction提供了MajorFunction更详细的信息

Flags

      Flags提供了函数期望驱动执行的附加信息

Control

       当内核驱动异步处理IRP时,驱动可以通过调用IoMarkIrpPending()IRP标记为Pending状态,以排队IRP处理。IoMarkIrpPending实际上只是将当前Stack LocationControl字段设定为SL_PENDING_RETURNED。内核驱动可以检查该字段查询是否有该标记。

DeviceObject

     当调用IoCallDriver()时,NT I/O管理器设定该字段,该字段的内容被设定为目标设备对象的指针。

Win2K源代码中可以看出上面的过程:

NTSTATUS

FASTCALL

IopfCallDriver(

    IN PDEVICE_OBJECT DeviceObject,

    IN OUT PIRP Irp

    )

 

/*++

Routine Description:

    This routine is invoked to pass an I/O Request Packet (IRP) to another

    driver at its dispatch routine.

Arguments:

    DeviceObject - Pointer to device object to which the IRP should be passed.

    Irp - Pointer to IRP for request.

Return Value:

    Return status from driver's dispatch routine.

--*/

{

    PIO_STACK_LOCATION irpSp;

    PDRIVER_OBJECT driverObject;

    NTSTATUS status;

    //

    // Ensure that this is really an I/O Request Packet.

    //

    ASSERT( Irp->Type == IO_TYPE_IRP );

    //

    // Update the IRP stack to point to the next location.

    //

    Irp->CurrentLocation--;

if (Irp->CurrentLocation <= 0)

{

        KeBugCheckEx( NO_MORE_IRP_STACK_LOCATIONS, (ULONG_PTR) Irp, 0, 0, 0 );

    }

    irpSp = IoGetNextIrpStackLocation( Irp );

    Irp->Tail.Overlay.CurrentStackLocation = irpSp;

    //

    // Save a pointer to the device object for this request so that it can

    // be used later in completion.

    //

    irpSp->DeviceObject = DeviceObject;

    //

    // Invoke the driver at its dispatch routine entry point.

    //

    driverObject = DeviceObject->DriverObject;

    PERFINFO_DRIVER_MAJORFUNCTION_CALL(Irp, irpSp, driverObject);

    status = driverObject->MajorFunction[irpSp->MajorFunction]( DeviceObject,

                                                              Irp );

    PERFINFO_DRIVER_MAJORFUNCTION_RETURN(Irp, irpSp, driverObject);

    return status;

}

FileObject

       I/O管理器将该字段设定为指向I/O操作的目标文件对象

CompletionRoutine

       当调用IoSetCompletionRoutine()函数时,设定该字段。I/O管理器在IRP处理完成时,要进行一系列的事后处理,其中就包括检查CompletionRoutine。如果指定了CompletionRoutine,该函数就将在执行事后处理的线程中调用;一般情况下就是调用IoCompleteRequest()函数的线程上下文中。

       CompletionRoutine采用堆栈顺序调用,即最后指定的CompletionRoutine最先调用,因此最高层驱动的完成函数最后被调用。如果某个驱动CompletionRoutine返回了STATUS_MORE_PROCESSING_REQUIREDI/O管理器将立即停止IRP事后处理。返回STATUS_MORE_PROCESSING_REQUIRED的驱动有责任释放IRP占用的内存。

       如果你开发一个高层的驱动程序,例如文件系统驱动或者过滤驱动,并且指定了一个Completion Routine。记得使用以下代码:

if(PtrIrp->PendingReturned)

{

IoMarkIrpPending(PtrIrp);

}

否则的话IRP处理将会出现错误。

Context

       该字段为Completion Routine提供参数 

<think>嗯,用户想知道如何使用boost::filesystem::last_write_time来获取文件的最后修改时间。首先,我需要回忆一下Boost.Filesystem库的相关函数。记得last_write_time有两个重载版本:一个用于获取时间,另一个用于设置时间。用户需要的是获取功能,所以应该用那个接受路径参数的版本。 接下来,函数返回的是一个std::time_t类型的时间戳。不过用户可能需要将其转换为可读的格式,比如本地时间。这时候需要用std::localtime函数转换,但要注意这个函数不是线程安全的。可能需要提醒用户这一点,或者建议使用其他方法,比如Boost.DateTime库中的功能。 然后,用户可能需要示例代码。我应该构造一个简单的例子,包含必要的头文件,比如boost/filesystem.hpp,以及处理异常的try-catch块。因为文件操作可能会抛出异常,特别是当路径不存在时,所以异常处理很重要。引用中的例子也提到了filesystem_error,所以需要捕获这个异常并处理。 另外,用户提供的引用里提到使用boost::filesystem::last_write_time,并且有一个参考链接,可能涉及到时区的问题。比如,返回的时间戳是否是本地时间还是UTC,是否需要调整时区。比如,在引用4中,用户提到时间可能少一个小时,这可能和时区转换有关。所以在示例代码中,可能需要指出如何正确转换时间,或者提醒用户注意时区的问题。 然后,关于代码部分,要确保路径正确,使用绝对路径或者相对路径。可能需要建议用户先检查文件是否存在,或者使用其他函数如is_regular_file来验证路径指向的是常规文件,避免对目录或符号链接进行操作。但根据用户的问题,可能只需要关注如何获取时间,所以示例可以简单一些。 最后,注意事项部分需要包括异常处理、时区问题、路径有效性检查,以及是否需要权限等。这些都是用户在实际使用中可能会遇到的问题,提前说明可以帮助他们避免错误。</think>以下是如何使用`boost::filesystem::last_write_time`获取文件最后修改时间的详细说明: --- ### 核心步骤 1. **包含头文件**:需包含`<boost/filesystem.hpp>` 2. **获取时间戳**:调用`boost::filesystem::last_write_time(path)`返回`std::time_t`类型的时间戳 3. **转换为可读格式**:通过`std::localtime`函数转换为本地时间结构`tm` ### 代码示例 ```cpp #include <iostream> #include <ctime> #include <boost/filesystem.hpp> int main() { boost::filesystem::path file_path = "test.txt"; // 替换为实际路径 try { if (boost::filesystem::exists(file_path)) { std::time_t t = boost::filesystem::last_write_time(file_path); std::tm* local_time = std::localtime(&t); std::cout << "最后修改时间: " << 1900 + local_time->tm_year << "-" << 1 + local_time->tm_mon << "-" << local_time->tm_mday << " " << local_time->tm_hour << ":" << local_time->tm_min << ":" << local_time->tm_sec << std::endl; } else { std::cout << "文件不存在" << std::endl; } } catch (const boost::filesystem::filesystem_error& e) { std::cerr << "文件操作异常: " << e.what() << std::endl; // 引用[2] } return 0; } ``` --- ### 关键注意事项 1. **异常处理**:必须捕获`filesystem_error`异常,例如路径非法或权限不足时会抛出[^2] 2. **时区问题**:`last_write_time`返回的是UTC时间戳,转换为本地时间可能涉及时区偏移(参考[^4]) 3. **路径有效性**:建议先用`boost::filesystem::exists`检查文件是否存在[^1] 4. **时间精度**:该函数返回的时间精度取决于文件系统实现(通常为秒级) ---
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值