在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.h
(Include.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";
}
如果我没记错的话,句柄是 table 中的一个索引,在每个进程的基础上进行维护。
对于 64 位 Windows,此 table 中的每个条目都由 8 字节的内核对象地址 + 4 字节的访问掩码组成,使条目的长度为 12 字节。但是据我了解,出于对齐目的,每个条目的长度为 16 个字节。
但是当您使用进程资源管理器查看进程打开的句柄时,句柄的值是 4 的倍数。这不应该是 16 的倍数吗?
一个Windows句柄本身就是一个索引,原则上可以是1的倍数。实施字(16 位值)对齐可能比您暗示的字节对齐更有效。
内核句柄的最低两位称为“标记位”,可供应用程序使用。这与句柄中条目的大小无关 table.
ntdef.h
(Include.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";
}