首先什么是 HANDLE

It’s an abstract reference value to a resource, often memory or an open file, or a pipe. (来自stackoverflow)
我个人的理解,HANDLE 就是一种为了统一资源的封装,所有的资源,内存,进程,甚至各种各样的设备,都可以通过 windows api,通过 handle 操作,拥有了 handle,就拥有了资源的操作权。比如说,在 windows 创建进程的过程中,通过 api monitor 可以很好的知道操作系统在用户态和内核交互的过程中做了什么,我们会发现为了创建一个进程,我们会获取一段内存,然后再把程序映射进去,对内存的操作也都是通过 HANDLE 传入传出实现的。

被面试官问了 HANDLE 和 PID 的关系

因为没有仔细分析,或者说是看过类似的资料,只能口糊一个。

HANDLE 和 PID 都是 32 位无符号整数。

系统,用户根据 pid 唯一确定一个进程
可以通过 handle 以及 每个进程的句柄表 获得内核对象的实际地址,是一种间接的映射。

曾经以前的认识,来自《WINDOWS核心编程》

1.调用了一个创建内核对象的函数时,函数会返回一个句柄,它标识了内核对象。

2.内核对象是由操作系统使用的,而非进程。

3.内核对象如果被别的进程使用,那么其中的计数器没有减到0该内核对象就不会被销毁。

4.进程初始化时,系统会给进程分配一个句柄表,这个表仅供内核对象使用,用户对象用不了,句柄表是一个数据结构组成的数组,每个结构都有 { 指向内核对象内存块的指针,访问掩码,标志}

5.进程首次初始化时,句柄表为空,当进程内的一个线程调用一个会创建内核对象的函数时,内核将会为这个对象分配并初始化一个内存块,然后内存扫描进程的句柄表,查找一个空白的记录项,然后写入到其中(系统干的!),其中指向内核对象的就是刚才那个进程初始化中的那个结构体的第一个参数。

6.那什么是handle呢,举一个例子

#...
/* 
HANDLE CreateFileMappingA(
  HANDLE                hFile,
  LPSECURITY_ATTRIBUTES lpFileMappingAttributes,
  DWORD                 flProtect,
  DWORD                 dwMaximumSizeHigh,
  DWORD                 dwMaximumSizeLow,
  LPCSTR                lpName
);
*/
int _tmain(int argc,TCHAR* argv[]){
    HANDLE file = CreateFileMappingA(
        hFile,
        lpFile,
        flProtect,
        dwMH,
        dwML,
        lpname
    );
    /*当程序从入口点进入,进入到了主函数(_tmain),会有一个进程产生,此时句柄表为空,进程本身啥也不干,贼懒,【】创建了一个主线程,然后开始运行,运行到下面发现有一个CreateFileMappingA()函数,进程知道要创建内核对象了,然后系统得知,系统再把这个内核对象写入到内存中(包括内存初始化),然后再把对应的指针,掩码,标志,写到句柄表中。这个句柄表只有内核才能操作,然后这个内核对象只能通过其句柄和一定的函数才能操作*/
    return 0;
}