关于句柄表的一些文章

2023-05-16

文章链接:

1> Windows内核情景分析 3.4.1 Windows 进程的句柄表

2> Windows 句柄表格式

3> Windows句柄表分配算法分析

4> 浅谈Windows句柄表

5> 句柄啊,3层表啊,ExpLookupHandleTableEntry啊... 5楼

--------------------------------------------------------------------------------------------

<ExpLookupHandleTableEntry笔记>

wrk1.2中

ExpLookupHandleTableEntry的内部流程
1) 取 Handle(EXHANDLE类型) 值为tHandle,并将TagBit(低两位)置0
2) 取 HandleTable->NextHandleNeedingPool为MaxHandle ,
   如果 tHandle大于等于MaxHandle,则返回NULL,查询失败
   (由此可见, NextHandleNeedingPool 应该是当前句柄表的最大句柄值+1
    或者说是下一个可用的句柄值)
3) 取 CapturedTable(ULONG_PTR类型)为HandleTable->TableCode
   取 TableLevel(ULONG)为(CapturedTable & LEVEL_CODE_MASK);
      (LEVEL_CODE_MASK=3,即由HandleTable->TableCode的低2位来指定句柄表的级数)
   CapturedTable 减去 TableLevel (即CapturedTable的低2位置0)
4) 根据 TableLevel 来进行不同方式的查找 

    令:
    PCHAR TableLevel1; 最低层的表指针
    PCHAR TableLevel2; 中间层的表指针
    PCHAR TableLevel3; 最上层的表指针
    ULONG_PTR i; 最低层的表索引
    ULONG_PTR j; 中间层的表索引
    ULONG_PTR k; 最上层的表索引
    PHANDLE_TABLE_ENTRY Entry 最后找到的句柄项目的指针

a) TableLeve = 0    句柄表只有1级,此时CapturedTable只是一个大小为512(4K/8=512)
     的HANDLE_TABLE_ENTRY数组,Handle的高30位即是索引.
     (当然,实际上因为一级表为512项,所以其实只有2~10 9位为有效索引,其中11~31位在
     第二步中被检查过,必为0).

     由于每个HANDLE_TABLE_ENTRY大小为8,所以对应的Entry相对于表起始地址的偏移
     为 Handle.Value>>2 * 8
  TableLevel1 = CapturedTable;
        Entry = TableLevel1 + (Handle.Value>>2) * 8
              = TableLevel1 + Handle.Index * 8
              = TableLevel1 + Handle.Value * 2 (因为第1步中已经将低2位置0了)

    wrk 1.2中代码如下

      Entry = (PHANDLE_TABLE_ENTRY) &TableLevel1[Handle.Value *
                               (sizeof (HANDLE_TABLE_ENTRY) / HANDLE_VALUE_INC)];

      其中HANDLE_VALUE_INC在EXHANDLE结构中定义,值是4

b) TableLeve = 1   句柄表有2级,
     第1层存储的是第2层表的指针(大小为4字节).
     第2层存储的是HANDLE_TABLE_ENTRY(大小为8个字节)
     
     句柄的2~10位为最底层表(第2层)的索引,11~N位为中间层表(第1层)索引
     (注:N的值从3层句柄表的情况看,应该为)

     wrk 1.2中的代码及分析如下
     +++++++++++++++++++++++++++++++++++++++++++++++
     i = Handle.Value % (LOWLEVEL_COUNT * HANDLE_VALUE_INC);
       /* 
       = Handle.Value % 0x800
       = Handle & 0x7FF 
       等效作用是取低11位 
       */

     Handle.Value -= i; 低11位置0

     j = Handle.Value / ((LOWLEVEL_COUNT * HANDLE_VALUE_INC) / sizeof (PHANDLE_TABLE_ENTRY));
       /* 
       = Handle.Value / (0x800 / 4)
       = (Handle.Value >> 11) * 4
       等效如下代码,实际上是取11~N为位为索引,并乘以4,得到中间表的表中偏移
       */

     TableLevel2 = (PUCHAR) CapturedTable;
     TableLevel1 =  *(PUCHAR)(TableLevel2 + j);
     Entry = TableLevel1+ (i * (sizeof (HANDLE_TABLE_ENTRY) / HANDLE_VALUE_INC));
           /*
           = TableLevel1+ (i*2)
           = TableLevel1+ ((i>>4) * 8)
           等效于最低层表索引(2~10位)乘以sizeof(HANDLE_TABLE_ENTRY),得到表中偏移.
           */
     ------------------------------------------------


c) TableLeve = 2  句柄表有3层 
     第1层存储的是第2层表的指针(大小为4字节).
     第2层存储的是第3层表的指针(大小为4字节).
     第3层存储的是HANDLE_TABLE_ENTRY(大小为8个字节)

     句柄的2~10位为最底层表(第3层)的索引,11~20位为中间层表(第2层)索引,
     20~N位为第一层索引(因为第1层最有4K/4个元素,索引应该也为10位,故推测
     N实际上应该为30)
     
     wrk 1.2中的代码及分析如下
     +++++++++++++++++++++++++++++++++++++++++++++++
     i = Handle.Value  % (LOWLEVEL_COUNT * HANDLE_VALUE_INC);

     Handle.Value -= i; 低11位清0

     k = Handle.Value / ((LOWLEVEL_COUNT * HANDLE_VALUE_INC) / sizeof (PHANDLE_TABLE_ENTRY));
       /*
       = Handle.Value / (0x800 / 4)
       = (Handle.Value >> 11) * 4 
       k取句柄的11~N为位,并乘以4
       */

     j = k % (MIDLEVEL_COUNT * sizeof (PHANDLE_TABLE_ENTRY));
       /*
       = k % (4K/4 * 4)
       = k % 0x1000
       = k & 0xFFF
       取k的低12位,实际上就是:句柄的11~20位为索引 * 4
       */

     k -= j; k的低12位清0

     k /= MIDLEVEL_COUNT;
       /*
       = k / (4k/4)
       = k / 0x1000
       = k >> 10
       取k的高10~N位,实际上就是句柄的21~N位为索引再乘以4
       */

     TableLevel3 = (PUCHAR) CapturedTable;
     TableLevel2 = (PUCHAR) *(PHANDLE_TABLE_ENTRY *) &TableLevel3[k];
     TableLevel1 = (PUCHAR) *(PHANDLE_TABLE_ENTRY *) &TableLevel2[j];
     Entry = (PHANDLE_TABLE_ENTRY) &TableLevel1[i * (sizeof (HANDLE_TABLE_ENTRY) / HANDLE_VALUE_INC)];

     ------------------------------------------------


<Windows句柄表格式>

句柄是Windows对象管理中引入的一个东西,它的实际意义是对象在句柄表中的索引。Windows2000使用的是固定的三层句柄表,而WindowsXP和Windows2003都是使用的动态可扩展的三层句柄表,这是一种很优秀的结构,易扩展,且查找迅速,值得学习。通常情况下每个进程的句柄表都是一级表,当句柄数超过一级表的容量时,就会扩展为二级表,此时二级表中放的是指向一级表的指针。同样,当二级表也放满时,就会扩展为三级表,里面放指向二级表的指针。但是通常我们看不到这种情况,因为就目前的大多数情况来说,二级表的容量已经够我们用了。
接下来具体地看一下进程的句柄表。每个进程都有一个句柄表,包括System进程(不过System的句柄表稍有点特殊),但是Idle除外,因为它并不是一个事实上真正的进程。在进程对象EPROCESS中,可以直接找到句柄表指针。
来找个进程对象看看:
lkd> dt _EPROCESS 8a92cb98
nt!_EPROCESS
   ...
   +0x0c4 ObjectTable      : 0xe23d3690 _HANDLE_TABLE
   ...
句柄表是一个HANDLE_TABLE结构,继续来看:
lkd> dt _HANDLE_TABLE 0xe23d3690
nt!_HANDLE_TABLE
   +0x000 TableCode        : 0xe3202001 //句柄表
   +0x004 QuotaProcess     : 0x89833da0 _EPROCESS //所属进程的EPROCESS
   +0x008 UniqueProcessId : 0x00000430 //所属进程的pid
   +0x00c HandleTableLock : [4] _EX_PUSH_LOCK //句柄表锁,用于进程某些操作时锁住句柄表
   +0x01c HandleTableList : _LIST_ENTRY [ 0xe216735c - 0xe2394fd4 ] //句柄表的双链,所有进程的句柄表链在一起,如果搞隐藏进程的话,这个地方是必须要照顾到的
   +0x024 HandleContentionEvent : _EX_PUSH_LOCK
   +0x028 DebugInfo        : (null)
   +0x02c ExtraInfoPages   : 0
   +0x030 FirstFree        : 0x114c
   +0x034 LastFree         : 0
   +0x038 NextHandleNeedingPool : 0x1800 //当前句柄表池的上界
   +0x03c HandleCount      : 1152 //当前进程中句柄总数
   +0x040 Flags            : 0
   +0x040 StrictFIFO       : 0y0
这里面最重要的,当然就是TableCode了。
TableCode的低两位被用作标志位,用于表示当前句柄表的级数,0,1,2分别表示一级表,二级表,三级表。
比如这里的0xe3202001 ,掩去高位,低两位的值为1,即为二级表。对于二级表,表中存放的是指向一级表的指针,一级表又被称为基本表,这实际上一个HANDLE_TABLE_ENTRY数组,它里面存放的HANDLE_TABLE_ENTRY中才是真正的对象,其定义如下:
typedef struct _HANDLE_TABLE_ENTRY {

    //
    // The pointer to the object overloaded with three ob attributes bits in
    // the lower order and the high bit to denote locked or unlocked entries
    //

    union {

        PVOID Object;

        ULONG ObAttributes;

        PHANDLE_TABLE_ENTRY_INFO InfoTable;

        ULONG_PTR Value;
    };

    //
    // This field either contains the granted access mask for the handle or an
    // ob variation that also stores the same information. Or in the case of
    // a free entry the field stores the index for the next free entry in the
    // free list. This is like a FAT chain, and is used instead of pointers
    // to make table duplication easier, because the entries can just be
    // copied without needing to modify pointers.
    //

    union {

        union {

            ACCESS_MASK GrantedAccess;

            struct {

                USHORT GrantedAccessIndex;
                USHORT CreatorBackTraceIndex;
            };
        };

        LONG NextFreeTableEntry;
    };

} HANDLE_TABLE_ENTRY, *PHANDLE_TABLE_ENTRY;
一级表可以放多大的句柄呢?按WRK中的宏展开,有
(TABLE_PAGE_SIZE / sizeof(HANDLE_TABLE_ENTRY))*HANDLE_VALUE_INC
即0x1000/8*4=0x800
计算过程:一级表(基本表)的大小为一页即4K=0x1000 Byte,而HANDLE_TABLE_ENRY大小为8字节,则可存放的个数为0x1000/8=0x200=512,而句柄以4为步进( 注0),因此最大句柄为0x200*4=0x800.其中可存放的最大句柄不超过0x800(最大为0x800-4),而每个一级表的第一个HANDLE_TABLE_ENTRY的Object总是为0,因为我们都知道0是一个无效的句柄,它不指向一个有效的对象。因此,每个一级表实际存放的句柄数为511个。我们当前查看的句柄表中共有句柄1152个,显然一个表是不够的,1152=511*2+130,这里显然需要三个表,且第三个表未放满。而TableCode值为0xe3202001,其低两位也说明了这是个二级表。掩去低两位之后才是二级表的真正地址。来查看一下:
lkd> dd 0xe3202000
e3202000 e2a7b000 e3203000 e2c1e000 00000000
e3202010 00000000 00000000 00000000 00000000
e3202020 00000000 00000000 00000000 00000000
e3202030 00000000 00000000 00000000 00000000
e3202040 00000000 00000000 00000000 00000000
没错的,二级表中放了三个一级表指针。再来查看一下第一个一级表的内容。
lkd> dd e2a7b000
e2a7b000 00000000 fffffffe e100b4e9 000f0003
e2a7b010 e1a9ef41 00000003 898343b3 00100020
e2a7b020 8982ece9 021f0003 e1a794e9 000f000f
e2a7b030 e23a61b9 021f0001 e2390a59 020f003f
明显看到,第一个HANDLE_TABLE_ENTRY的Object为0.从第二个起才是有效的对象(如果某对象所对应的句柄被关闭,那么该对象就会从相应的句柄表中删除,所以并非句柄表中的每个位置存放的都是有效对象)。
接下来看HANDLE_TABLE_ENTRY,e100b4e9 000f0003这一对数据就是HANDLE_TABLE_ENTRY结构中的Object和GrantedAccess了。但是这里的Object并不是直接指向对象的。因为对象体总是8字节对齐,所以地址的低三位总是0,因此被用于标志位,表明该对象所对应的句柄的一些属性,比如可继承等等。因此,要对这里得到的Object掩去低三位,才会得到一个指向对象头OBJECT_HEADER的指针。
e100b4e9这里掩去之后为e100b4e8
lkd> dt _OBJECT_HEADER e100b4e8
nt!_OBJECT_HEADER
   +0x000 PointerCount     : 28
   +0x004 HandleCount      : 27
   +0x004 NextToFree       : 0x0000001b
   +0x008 Type             : 0x8a928e70 _OBJECT_TYPE
   +0x00c NameInfoOffset   : 0x20 ' '
   +0x00d HandleInfoOffset : 0 ''
   +0x00e QuotaInfoOffset : 0 ''
   +0x00f Flags            : 0x36 '6'
   +0x010 ObjectCreateInfo : 0x00000001 _OBJECT_CREATE_INFORMATION
   +0x010 QuotaBlockCharged : 0x00000001
   +0x014 SecurityDescriptor : 0xe100b44d
   +0x018 Body             : _QUAD
继续来看一下这个OBJECT_TYPE
lkd> dt _OBJECT_TYPE 0x8a928e70
nt!_OBJECT_TYPE
   +0x000 Mutex            : _ERESOURCE
   +0x038 TypeList         : _LIST_ENTRY [ 0xe100b4d8 - 0xe100b4d8 ]
   +0x040 Name             : _UNICODE_STRING "KeyedEvent"
   +0x048 DefaultObject    : 0x80568b40
   +0x04c Index            : 0x10
   +0x050 TotalNumberOfObjects : 1
   +0x054 TotalNumberOfHandles : 0x1b
   +0x058 HighWaterNumberOfObjects : 1
   +0x05c HighWaterNumberOfHandles : 0x1b
   +0x060 TypeInfo         : _OBJECT_TYPE_INITIALIZER
   +0x0ac Key              : 0x6579654b
   +0x0b0 ObjectLocks      : [4] _ERESOURCE
是个KeyedEvent对象。对象头再加上它本身的大小0x18之后就到了对象体OJBECT_BODY了,这个因不同对象而异。直接来看一下:
lkd> !object e100b4e8+0x18
Object: e100b500 Type: (8a928e70) KeyedEvent
    ObjectHeader: e100b4e8 (old version)
    HandleCount: 27 PointerCount: 28
    Directory Object: e10000a8 Name: CritSecOutOfMemoryEvent
跟前面看到的对比一下,完全是一致的。这样就了解了如何从进程的句柄表中得到实际的对象。
下面以该进程中的一个句柄0x1078为例说明句柄如何索引到对象。
0x1078/0x800=2
0x1078%0x800=0x78
前面已经知道,该进程的句柄表为二级表,而上面的计算结果表明,该句柄大小已经超出了两个句柄表的范围,在第三个句柄表中,且偏移为0x78*2.(因为句柄按4递增,而HANDLE_TABLE_ENTRY结构大小为8,所以正确公式应该为0x78除以4得到索引值,再乘以8得到以字节计算的偏移值,结果即0x78*2)
而第三张表基址为e2c1e000 。来看一下:
lkd> dd e2c1e000+0x78*2
e2c1e0f0 896b7019 001f03ff 8984e659 00100003
e2c1e100 8984e611 00100003 e2d183d9 00020019
e2c1e110 898003f1 001f0003 896c0701 0012019f
e2c1e120 8984e5c9 00100003 89834691 00100003
可以得到Object为896b7019,掩去低两位,则对象头指针为896b7018,对象体指针为896b7018+0x18
lkd> !object 896b7018+0x18
Object: 896b7030 Type: (8a92c040) Thread
    ObjectHeader: 896b7018 (old version)
    HandleCount: 3 PointerCount: 5
结果显示这是一个线程对象,与Process Explorer中显示的结果完全一致。以上过程很容易转化为程序实现并且不依赖任何系统函数,具体实现过程可参考WRK中的ExpLookupHandleTableEntry 函数,其原型为
PHANDLE_TABLE_ENTRY
ExpLookupHandleTableEntry (
    IN PHANDLE_TABLE HandleTable,
    IN EXHANDLE tHandle
    );

---------------------------------------------------------------------------------------------------------

注0: 这里需要这样理解: 句柄的值是4对齐的, 即4, 8, c, f, 10等等, 也就是说, 索引为1句柄为4, 句柄是索引的4倍, 所以要乘以4. 这里参考文章<浅谈Windows句柄表>

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

关于句柄表的一些文章 的相关文章

  • 编译错误“Too many arguments to function call....”

    运行编译过程中出现错误 xff0c 并提示 Too many arguments to functions call expected 的信息 xff0c 如图一 遇到这种情况时 xff0c 该如何解决呢 xff1f 解决方法是将属性 En
  • CocoaPods的使用——cocoapods的升级更新

    最近使用cocoa pods时提示版本过低需要升级才能正常使用 但是在升级过程中又出现了问题 首先我是直接使用语句 xff1a sudo gem install cocoapods 进行更新升级的 xff0c 没想到又报错了 接着我在想是不
  • http请求方法(GET、POST、HEAD、OPTIONS、PUT、DELETE、TRACE、CONNECT)

    根据HTTP标准 xff0c HTTP请求可以使用多种请求方法 HTTP的1 0版本中只有三种请求方法 xff1a GET POST 和 HEAD方法 到了1 1版本时 xff0c 新增加了五种请求方法 xff1a OPTIONS PUT
  • MongoDB可视化工具 Studio 3T

    告别终端使用可视化工具Studio 3T对MongoDB进行数据库的操作 简单的使用步骤介绍 1 启动MongoDB服务器 xff08 方法见MongoDB介绍与安装中的介绍 xff09 2 连接MongoDB服务器 3 操作数据库
  • 微信小程序开发——form表单

    WeChat小程序交流 xff08 QQ群 xff1a 769977169 xff09 效果图 代码示例 1 xxx wxml lt form bindsubmit 61 39 submitClick 39 bindreset 61 39
  • 苹果电脑(Mac mini或Macbook或iMac)恢复出厂设置

    苹果电脑 xff08 Mac mini或Macbook或iMac xff09 恢复出厂设置 xff0c 首先要做好如下的准备 xff1a 第一 xff1a 数据的备份 xff1b 第二 xff1a 保证正常的wifi连接 xff1b 第三
  • VSLAM基础(一)————常见特征点提取算法及匹配优化

    过年期间闲来无事 xff0c 就想来把这半年学习的一些视觉知识 xff08 视觉slam相关 xff09 做个梳理 xff0c 就以这篇图像特征点提取与匹配作为开头吧 一 关键点与描述子 关键点 xff1a 图像上某些特殊的 具有代表的点
  • 【2017CS231n】第十五讲:神经网络模型压缩和加速(硬件、算法层面)

    一 算法 1 剪枝 不是所有的神经网络连接都有用 减少连接 xff0c 但不降低准确性 尝试性 xff1a 剪枝 xff0c 训练不断重复 xff0c 找到对准确性影响最高的那一部分连接 2 参数共享 1 98 2 09 1 92 1 87
  • 程序员面试等通知一般多久?

    最近面试的人比较多 xff0c 毕竟是金三银四嘛 xff0c 竞争也挺大的 xff0c 很多人在面试之后 xff0c 久久没有收到入职通知 xff0c 等待是一件非常痛苦的事情 那么程序员面试等通知一般多久 xff1f 多久没有发通知就等于
  • 程序员简历项目经验怎么写?

    我是一个典型的互联网公司程序员 xff0c 也见过无数的程序员简历 xff0c 包括很多优秀的程序员简历 xff0c 看了可以让人眼前一亮 xff0c 优美简洁的简历模板 xff0c 项目经验工作重点突出 也见过更多的写得不好的简历 程序员
  • OpenRAVE

    机器人的高级功能 机械手臂控制 软件方面 在ros里 有moveit 研究的过程中 扩展到了openrave专业包 Welcome to OpenRAVE Latest Official Release 0 8 2 OpenRAVE pro
  • C++——STL初识

    一 为什么需要STL xff1f 目的 xff1a 为了建立一套重复利用的东西 使用STL可以避免从事大量重复的工作 为建立数据结构的一套标准 xff0c 诞生了STL 二 基本概念 STL是标准模板库 STL从广义上分为 xff1a 容器
  • Showing progress bar in a status bar pane

    This article was contributed by Brad Mann This code creates a progress bar anywhere in the status window and the control
  • 大小端字节序转换

    特点 各主机的字节序可能不同 xff0c 网络协议指定的通讯字节序为大端 只有在多字节数据处理时才需要考虑字节序 运行在同一台计算机的进程互相通信时 xff0c 不需要考虑字节序 二 字节序转换函数 头文件 xff1a include lt
  • 51单片机控制0.96寸OLED(IIC接口)

    1 OLED初步认识 OLED Organic Light Emitting Diode xff0c 即有机发光二极管 OLED由于同时具备自发光 xff0c 不需背光源 xff0c 对比度高 xff0c 厚度薄 xff0c 视角广 xff
  • 51单片机控制LCD1602模块

    51单片机控制LCD1602模块 视频播放 xff1a LCD1602视频 xff08 1 xff09 LCD1602概述 先来看看LCD1602什么意思 xff1f Liquid Crystal Display LCD 表示液晶显示 xf
  • LCD1602模块如何显示自定义字符

    相信大家现在知道了如何通过查字库表的方法来显示表中的任意一个字符 假如现在我想显示某个温度值 xff0c 需要标志出温度符号 C xff0c 现在你去字库表里面查找 xff0c 发现根本找不到这个符号 xff0c 那怎么办 xff1f 下面
  • 51单片机控制温度传感器DS18B20

    xff08 1 xff09 DS18B20初步认识 DS18B20是美国DALLAS半导体公司推出的一种数字化单总线器件 xff0c 属于新一代适配微处理器的改进型智能温度传感器 我们先来看看DS18B20在芯片手册上的标题 DS18B20
  • ESP8266模块手机端和电脑端网络调试助手

    ESP8266模块手机端和电脑端网络调试助手 使用方法比较简单 xff0c 如下界面所示 xff1a 电脑端 xff1a 确定 协议类型 xff0c 34 IP地址 34 和 34 端口 34 xff0c 然后点击连接即可 xff0c 如下
  • Micro Python 入门教程-pyboard V1.1控制LCD1602液晶显示模块

    11 LCD1602液晶显示模块 11 1 初识LCD1602液晶模块 LCD1602什么意思 xff0c LCD表示Liquid Crystal Display xff0c 1602表示一行可以显示16个字符 xff0c 一共有两行 实物

随机推荐

  • 常见无人机自组网路由协议

    常见无人机自组网路由协议 无人机自组网路由协议静态路由协议先验式路由协议反应式路由协议 无人机自组网路由协议 为了适应无人机组网节点高速移动带来的网络拓扑结构快速变化 xff0c 无人机自组网使用的路由协议主要有以下几种 静态路由协议 这种
  • 尚硅谷大数据项目之Flink实时数仓-踩坑记录和笔记记录

    这里写自定义目录标题 1 关于Slf4j注解配置文件logback xml不生效问题2 判断新老用户的时候 xff0c 什么时候会出问题 xff1a 3 为什么维度数据选择存储在Hbase中 xff0c 而不是Redis xff0c Mys
  • 【学习笔记】尚硅谷大数据项目之Flink实时数仓---数据可视化接口实现

    这里写自定义目录标题 第 1 章 数据可视化接口1 1 设计思路1 2 需求梳理1 2 1 最终显示效果图1 2 2 分析可视化大屏1 2 3 接口执行过程 第 2 章 Sugar 数据大屏2 1 产品介绍2 2 使用入口2 3 创建数据大
  • VR发展前景展望

    VR发展前景展望 引子 随着计算机技术的飞速发展 xff0c 虚拟现实也在短时间内经历了萌芽探索到飞速发展完善的转变 由于其独特的沉浸式体验 xff0c VR的前景被大多数人看好 xff0c 更多的VR相关技术也在为让人能更完美的融合到这个
  • Ubuntu18.04下C++分文件编写报错:对‘Class::Func()’未定义的引用解决办法

    源代码结构 如图所示 xff0c 编写一个员工管理系统 xff0c 在WorkerManager h中声明类和函数 xff0c 在WorkerManager cpp中写具体实现在staffManagementSystem cpp中实例化类
  • 人工智能是什么?

    人工智能是什么 xff1f 欢迎大家迈入人工智能的大门1 人工智能的定义2 人工智能的话题3 人工智能的四大技术分支4 人工智能的主要应用领域5 人工智能的三种形态5 1 弱人工智能到强人工智能有多难 xff1f 5 2 弱人工智能的前进方
  • 浏览器-基本认证(Basic Authentication)-摘要认证(digest authentication)=spring boot实现demo

    平时开发的 java web 网站登录 xff0c 都是通过表单提交登录信息 有时一些中间件登录是浏览器弹窗 xff0c 没有看到表单实现代码 故通过查询 xff0c 发现两种 HTTP 简单认证 xff1a 基本认证 Basic Auth
  • PX4 gazebo仿真 2023.4.13更新

    前言 想实现px4仿真 xff0c 考虑使用gazebo仿真 去PX4官网看一眼先 xff0c 官网提到后面如果要用ROS xff0c 直接配置ROS就好了 xff0c 不然会不兼容 xff0c 那么就按官网步骤走 官网步骤 结果第一步就失
  • PX4 & gazebo仿真 offboard模式无法起飞解决思路

    前言 我用最新版PX4固件 xff0c offboard模式飞机无法起飞 xff0c 网上有一种说法是固件版本的问题 xff0c 让用旧一点的版本 添加链接描述 这个链接描述的情况和我的一模一样 xff0c 所以我肯定是按这个方法尝试的 旧
  • 数字图传VS模拟图传 图传技术知识 2023.3.6更新

    引言 在研究无人机小半年了 xff0c 多次听到数字图传和模拟图传字眼 xff0c 一直都是一知半解 xff0c 这次整体了解一下并加以 整理 数字图传 数字图传 xff1a 指数字化的图像信号经信源编码和信道编码 xff0c 通过数字信道
  • 069-线性系统的可控性和可观测性

    对一个线性系统 xff0c 需要判定其可控性或者可观测性 xff0c 才能对其进行求解 或者说的狭义一点 xff0c 在一个卡尔曼滤波模型中 xff0c 只有判定了其可控性 xff0c 才能知晓状态向量X中多少个状态是可观测的 比如X中原有
  • 滴水石穿

    不积跬步 xff0c 无以至千里 xff1b 不积小流 xff0c 无以成江海 1 hashcode相等两个类一定相等吗 equals呢 相反呢 hashcode相等 xff0c 两个类不一定相等 xff1b equals相等 xff0c
  • C++编程——友元

    文章目录 1 友元的概念2 友元的三种实现2 1 全局函数做友元2 2 类做友元2 3 成员函数做友元 1 友元的概念 友元目的是让一个函数或者类访问另一个类中的私有成员 有一个非常生动的例子 xff0c 就是家中会有客厅和卧室 xff0c
  • C++编程——多态

    文章目录 1 多态的基本概念1 1 函数地址早绑定1 2 地址晚绑定 2 多态的原理3 多态的优点与案例3 1 多态的优点3 2 计算器实现案例 4 纯虚函数与抽象类5 虚析构与纯虚析构5 1 虚析构实现5 2 纯虚析构实现 多态的知识结构
  • 自动驾驶常用数据集KITTI使用指南之一——图像雷达数据融合

    对于自动驾驶环境感知算法的初学者而言 xff0c 一辆搭载各类传感器的自动驾驶汽车或者数据采集平台并没有那么重要 xff0c 甚至 xff0c 由于国外早期自动驾驶研究学者的严谨态度 xff0c 一些公开的数据集比自己采集的数据集在同步性
  • 笔试题

    杭州公交云笔试题 输入一个字符串用逗号隔开 xff0c 找出其中最大的连续递增个数 例如 xff1a 1 xff0c 2 xff0c 3 xff0c 1 xff0c 1 xff0c 1 返回3 import java util public
  • C++STL迭代器

    迭代器 1 迭代器 xff1a 类中类 xff0c 通过运算符的重载 xff0c 用类中类的对象遍历容器 2 迭代器分类 xff1a xff08 1 xff09 正向迭代器 xff1a iterator xff08 begin end xf
  • Dockerfile详细解析(四)——环境变量

    环境变量 xff08 Environment replacement xff09 环境变量 xff08 使用 ENV 表达式声明 xff09 也可以被用在某些确定的指令中作为变量被Dockerfile解释出来 Escapes 也被处理为类似
  • STM32 FreeRTOS系列教程(一)FreeRTOS简介

    参考资料 xff1a 正点原子STM32F4 FreeRTOS开发手册 V1 1 野火FreeRTOS 内核实现与应用开发实战 基于STM32 学习RTOS的意义 当我们进入嵌入式这个领域的时候 xff0c 往往首先接触的都是单片机编程 x
  • 关于句柄表的一些文章

    文章链接 1 gt Windows内核情景分析 3 4 1 Windows 进程的句柄表 2 gt Windows 句柄表格式 3 gt Windows句柄表分配算法分析 4 gt 浅谈Windows句柄表 5 gt 句柄啊 3层表啊 Ex