在windows中,句柄值为什么是4的倍数?

In windows, Why the handle value is in multiple of 4?

如果我没记错的话,句柄是 table 中的一个索引,在每个进程的基础上进行维护。

对于 64 位 Windows,此 table 中的每个条目都由 8 字节的内核对象地址 + 4 字节的访问掩码组成,使条目的长度为 12 字节。但是据我了解,出于对齐目的,每个条目的长度为 16 个字节。

但是当您使用进程资源管理器查看进程打开的句柄时,句柄的值是 4 的倍数。这不应该是 16 的倍数吗?

一个Windows句柄本身就是一个索引,原则上可以是1的倍数。实施字(16 位值)对齐可能比您暗示的字节对齐更有效。

内核句柄的最低两位称为“标记位”,可供应用程序使用。这与句柄中条目的大小无关 table.

ntdef.hInclude.0.x.x\shared)中的评论说:

//
// Low order two bits of a handle are ignored by the system and available
// for use by application code as tag bits.  The remaining bits are opaque
// and used to store a serial number and table index.
//

#define OBJ_HANDLE_TAGBITS  0x00000003L

我的猜测是,这是一种类似的误用,例如将 32 位指针的最高有效位用作布尔标志,这就是我们拥有 LAA(大地址感知)和非 LAA 应用程序的原因。

您可以(但不应该)将 1、2 或 3 添加到 HANDLE,并且它不应影响其他 Windows API 方法。例如。 WaitForSingleObject():

#include <iostream>
#include <windows.h>
int main()
{
    STARTUPINFO si;
    PROCESS_INFORMATION pi;
    ZeroMemory(&si, sizeof(si));
    si.cb = sizeof(si);
    ZeroMemory(&pi, sizeof(pi));
    auto created = CreateProcess(L"C:\Windows\System32\cmd.exe",
        nullptr, nullptr, nullptr, FALSE, 0, nullptr, nullptr, &si, &pi
    );
    if (created)
    {
        pi.hProcess = static_cast<byte*>(pi.hProcess) + 3;
        const auto result = WaitForSingleObject(pi.hProcess, INFINITE);
        if (result == 0)
            std::cout << "Completed!\n";
        else
            std::cout << "Failed!\n" << result << "\n";
        CloseHandle(pi.hProcess);
        CloseHandle(pi.hThread);
    }
    else
        std::cout << "Not created";
}