分享
 
 
 

JIURL玩玩Win2k内存篇 LookasideList

王朝vc·作者佚名  2006-01-08
窄屏简体版  字體: |||超大  

JIURL玩玩Win2k内存篇 LookasideList

作者: JIURL

主页: http://jiurl.yeah.net

日期: 2003-7-30

系统的堆的简介

系统的堆是系统的数据动态申请和释放的地方。Win2k 把系统堆叫做 pool。根据是否可以被换出物理内存,分为 PagedPool 和 NonPagedPool。

LookasideList

Windows 2000 中有很多种结构,这些结构需要动态申请。也就是在系统的 pool 中申请。在 pool 中申请和释放内存都是比较慢的,因为申请的时候需要在 pool 中寻找合适大小的空闲块,释放的时候还要考虑合并空闲块,等等繁琐的操作。系统中有很多很多的固定大小的结构需要动态分配,为了提高效率,系统使用了 LookasideList 。

Windows 2000 中有很多的 LookasideList 。某种 LookasideList 申请固定大小的存。LookasideList 从 Paged pool 或者 Nonpaged pool 中申请内存。对于 LookasideList 上的块释放的时候,它并不是被直接释放到 pool 中,而有可能放在 LookasideList 上,这样如果再有申请的话,就不用再去 pool 中查找合适大小的空闲块,而可以直接取走使用了。也就是申请的时候,仍然是去 pool 中申请一块一定大小的内存。但是释放的时候,很有可能并不释放回堆里去,而是被 LookasideList 保留下来,供再申请的时候使用。后面我们将会发现系统中 LookasideList 的数量很多,如果申请过的块都不被释放的话,那不是要白白占用很多内存,有可能导致别人的新的申请申请不到内存?不必担心,每个 LookasideList 最多只保留很少的几块,如果超过,就会释放回 pool 里去。系统也会定时检查。

Windows 2000 把很多 LookasideList 链在两个链上。根据该 LookasideList 是从 Paged pool 还是从 Nonpaged pool 中申请内存。从 Paged pool 中申请内存的 LookasideList 链在 PagedLookasideList 上。

从 Nonpaged pool 中申请内存的 LookasideList 链在 NPagedLookasideList 上。

在 ntddk.h 中有两种 LookasideList (NPAGED_LOOKASIDE_LIST 和 PAGED_LOOKASIDE_LIST) 及其相关结构的定义。通过 kd 也可以得到他们的结构定义。

typedef struct _NPAGED_LOOKASIDE_LIST {

GENERAL_LOOKASIDE L;

KSPIN_LOCK Lock;

} NPAGED_LOOKASIDE_LIST, *PNPAGED_LOOKASIDE_LIST;

typedef struct _PAGED_LOOKASIDE_LIST {

GENERAL_LOOKASIDE L;

FAST_MUTEX Lock;

} PAGED_LOOKASIDE_LIST, *PPAGED_LOOKASIDE_LIST;

kd> !strct GENERAL_LOOKASIDE

!strct GENERAL_LOOKASIDE

struct _GENERAL_LOOKASIDE (sizeof=72)

+00 union _SLIST_HEADER ListHead

+00 uint64 Alignment

+00 struct _SINGLE_LIST_ENTRY Next

+00 struct _SINGLE_LIST_ENTRY *Next

+04 uint16 Depth

+06 uint16 Sequence

+08 uint16 Depth

+0a uint16 MaximumDepth

+0c uint32 TotalAllocates

+10 uint32 AllocateMisses

+10 uint32 AllocateHits

+14 uint32 TotalFrees

+18 uint32 FreeMisses

+18 uint32 FreeHits

+1c int32 Type

// 表明是 NPAGED 还是 PAGED。 为0表示NPAGED 。为1表示PAGED。

+20 uint32 Tag

// 4个字节,通常放入4个字母来作为标记。比如 ObpCreateInfoLookasideList 使用 "ObCi"。

+24 uint32 Size

// 这个 LookasideList 上每项的大小。

+28 function *Allocate

// 申请函数,通常放 ExAllocatePoolWithTag

+2c function *Free

// 释放函数,通常放 ExFreePool

+30 struct _LIST_ENTRY ListEntry

+30 struct _LIST_ENTRY *Flink

+34 struct _LIST_ENTRY *Blink

// 这里把同一种类型(NPAGED 或者 PAGED)的 LookasideList 链在一起。

+38 uint32 LastTotalAllocates

+3c uint32 LastAllocateMisses

+3c uint32 LastAllocateHits

+40 uint32 Future[2]

typedef struct _SINGLE_LIST_ENTRY {

struct _SINGLE_LIST_ENTRY *Next;

} SINGLE_LIST_ENTRY, *PSINGLE_LIST_ENTRY;

下面我们使用 kd 分别遍历这两个链表

遍历 PagedLookasideList

kd> ? ExPagedLookasideListHead

? ExPagedLookasideListHead

Evaluate expression: -2142817432 = 80473368

// 全局变量 ExPagedLookasideListHead

kd> !strct LIST_ENTRY ExPagedLookasideListHead

!strct LIST_ENTRY ExPagedLookasideListHead

struct _LIST_ENTRY (sizeof=8)

+0 struct _LIST_ENTRY *Flink = 8046A9D0

+4 struct _LIST_ENTRY *Blink = 810EAF38

// PagedLookasideList 链上的 PAGED_LOOKASIDE_LIST 结构中的 LIST_ENTRY ListEntry

!strct PAGED_LOOKASIDE_LIST

struct _PAGED_LOOKASIDE_LIST (sizeof=104)

...

+30 struct _LIST_ENTRY ListEntry

...

kd> ? 8046A9D0-30

? 8046A9D0-30

Evaluate expression: -2142852704 = 8046a9a0

// 验证一下

kd> !lookaside 8046a9a0

!lookaside 8046a9a0

Lookaside "" @ 8046a9a0 "TunL"

Type = 0001 PagedPool

Current Depth = 1 Max Depth = 4

Size = 136 Max Alloc = 544

AllocateMisses = 293 FreeMisses = 283

TotalAllocates = 478 TotalFrees = 469

Hit Rate = 38% Hit Rate = 39%

kd> !strct PAGED_LOOKASIDE_LIST 8046a9a0

!strct PAGED_LOOKASIDE_LIST 8046a9a0

struct _PAGED_LOOKASIDE_LIST (sizeof=104)

+00 struct _GENERAL_LOOKASIDE L

+00 union _SLIST_HEADER ListHead

+00 uint64 Alignment = 01730001e35116c8

+00 struct _SINGLE_LIST_ENTRY Next

+00 struct _SINGLE_LIST_ENTRY *Next = E35116C8

+04 uint16 Depth = 0001

+06 uint16 Sequence = 0173

+08 uint16 Depth = 0004

+0a uint16 MaximumDepth = 0100

+0c uint32 TotalAllocates = 000001de

+10 uint32 AllocateMisses = 00000125

+10 uint32 AllocateHits = 00000125

+14 uint32 TotalFrees = 000001d5

+18 uint32 FreeMisses = 0000011b

+18 uint32 FreeHits = 0000011b

+1c int32 Type = 00000001 // 1=PagedPool

+20 uint32 Tag = 4c6e7554

+24 uint32 Size = 00000088 // 0x88=136

+28 function *Allocate = 80466C80

+2c function *Free = 80467297

+30 struct _LIST_ENTRY ListEntry

+30 struct _LIST_ENTRY *Flink = 804734B0

+34 struct _LIST_ENTRY *Blink = 80473368

+38 uint32 LastTotalAllocates = 000001dd

+3c uint32 LastAllocateMisses = 00000125

+3c uint32 LastAllocateHits = 00000125

+40 uint32 Future[2] = 00000000 00000000 .... ....

+48 struct _FAST_MUTEX Lock

+48 int32 Count = 00000001

+4c struct _KTHREAD *Owner = 00000000

+50 uint32 Contention = 00000000

+54 struct _KEVENT Event

+54 struct _DISPATCHER_HEADER Header

+54 byte Type = 01 .

+55 byte Absolute = 00 .

+56 byte Size = 04 .

+57 byte Inserted = 00 .

+58 int32 SignalState = 00000000

+5c struct _LIST_ENTRY WaitListHead

+5c struct _LIST_ENTRY *Flink = 8046A9FC //

+60 struct _LIST_ENTRY *Blink = 8046A9FC

+64 uint32 OldIrql = 00000000

kd> dd ExPagedLookasideListHead l 2

dd ExPagedLookasideListHead l 2

80473368 8046a9d0 810eaf38

// 记住我们是从 ExPagedLookasideListHead 80473368 开始的,当我们再看到 80473368

// 就表示链已经循环了。

kd> dd $p l 2

dd $p l 2

8046a9d0 804734b0 80473368

kd>

804734b0 80473730 8046a9d0

kd>

80473730 804802f0 804734b0

kd>

804802f0 80480a90 80473730

kd>

80480a90 fcccd4b0 804802f0

kd>

fcccd4b0 fcccd590 80480a90

kd>

fcccd590 810eba38 fcccd4b0

kd>

810eba38 810eb918 fcccd590

kd>

810eb918 810eb898 810eba38

kd>

810eb898 810eb818 810eb918

kd>

810eb818 810eb798 810eb898

kd>

810eb798 810eb718 810eb818

kd>

810eb718 810eb698 810eb798

kd>

810eb698 810ea038 810eb718

kd>

810ea038 810eafb8 810eb698

kd>

810eafb8 810eaf38 810ea038

kd>

810eaf38 80473368 810eafb8

kd>

80473368 8046a9d0 810eaf38

// 我们又看到了 80473368 ,表示链已经循环了

遍历 NPagedLookasideList

kd> ? ExNPagedLookasideListHead

? ExNPagedLookasideListHead

Evaluate expression: -2142817416 = 80473378

kd> !strct LIST_ENTRY ExNPagedLookasideListHead

!strct LIST_ENTRY ExNPagedLookasideListHead

struct _LIST_ENTRY (sizeof=8)

+0 struct _LIST_ENTRY *Flink = 8047F8D0

+4 struct _LIST_ENTRY *Blink = EEFFEC90

kd> !strct NPAGED_LOOKASIDE_LIST

!strct NPAGED_LOOKASIDE_LIST

struct _NPAGED_LOOKASIDE_LIST (sizeof=80)

...

+30 struct _LIST_ENTRY ListEntry

...

kd> ? 8047F8D0-30

? 8047F8D0-30

Evaluate expression: -2142766944 = 8047f8a0

kd> !lookaside 8047f8a0

!lookaside 8047f8a0

Lookaside "" @ 8047f8a0 "ObCi"

Type = 0000 NonPagedPool

Current Depth = 2 Max Depth = 4

Size = 48 Max Alloc = 192

AllocateMisses = 24 FreeMisses = 0

TotalAllocates = 73 TotalFrees = 51

Hit Rate = 67% Hit Rate = 100%

kd> !strct NPAGED_LOOKASIDE_LIST 8047f8a0

!strct NPAGED_LOOKASIDE_LIST 8047f8a0

struct _NPAGED_LOOKASIDE_LIST (sizeof=80)

+00 struct _GENERAL_LOOKASIDE L

+00 union _SLIST_HEADER ListHead

+00 uint64 Alignment = 0064000281feeb88

+00 struct _SINGLE_LIST_ENTRY Next

+00 struct _SINGLE_LIST_ENTRY *Next = 81FEEB88

+04 uint16 Depth = 0002

+06 uint16 Sequence = 0064

+08 uint16 Depth = 0004

+0a uint16 MaximumDepth = 0100

+0c uint32 TotalAllocates = 00000049

+10 uint32 AllocateMisses = 00000018

+10 uint32 AllocateHits = 00000018

+14 uint32 TotalFrees = 00000033

+18 uint32 FreeMisses = 00000000

+18 uint32 FreeHits = 00000000

+1c int32 Type = 00000000

+20 uint32 Tag = 6943624f

+24 uint32 Size = 00000030

+28 function *Allocate = 80466C80

+2c function *Free = 80467297

+30 struct _LIST_ENTRY ListEntry

+30 struct _LIST_ENTRY *Flink = 8047F930

+34 struct _LIST_ENTRY *Blink = 80473378

+38 uint32 LastTotalAllocates = 00000049

+3c uint32 LastAllocateMisses = 00000018

+3c uint32 LastAllocateHits = 00000018

+40 uint32 Future[2] = 00000000 00000000 .... .

...

+48 uint32 Lock = 00000000

kd> dd ExNPagedLookasideListHead l 2

dd ExNPagedLookasideListHead l 2

80473378 8047f8d0 eeffec90

// 记住我们是从 ExPagedLookasideListHead 80473378 开始的,当我们再看到 80473378

// 就表示链已经循环了。

kd> dd $p l 2

dd $p l 2

8047f8d0 8047f930 80473378

kd>

8047f930 814521f8 8047f8d0

kd>

814521f8 81452198 8047f930

kd>

81452198 80472130 814521f8

kd>

80472130 8141b1b8 81452198

kd>

8141b1b8 80473650 80472130

kd>

80473650 804736b0 8141b1b8

kd>

804736b0 80473530 80473650

kd>

80473530 80473590 804736b0

kd>

80473590 804735f0 80473530

kd>

804735f0 804737b0 80473590

kd>

804737b0 80475830 804735f0

kd>

80475830 804756d0 804737b0

kd>

804756d0 804758d0 80475830

kd>

804758d0 80475770 804756d0

kd>

80475770 8141a2f8 804758d0

kd>

8141a2f8 81416d18 80475770

kd>

81416d18 81416cb8 8141a2f8

kd>

81416cb8 81416c58 81416d18

kd>

81416c58 80480b30 81416cb8

kd>

80480b30 fcd5c510 81416c58

kd>

fcd5c510 fcd5c1b0 80480b30

kd>

fcd5c1b0 fcd5c390 fcd5c510

kd>

fcd5c390 fcd5c290 fcd5c1b0

kd>

fcd5c290 fcd5c0f0 fcd5c390

kd>

fcd5c0f0 fcd1e9b0 fcd5c290

kd>

fcd1e9b0 fcd1ea00 fcd5c0f0

kd>

fcd1ea00 813d0618 fcd1e9b0

kd>

813d0618 813cf3d8 fcd1ea00

kd>

813cf3d8 813f6ef8 813d0618

kd>

813f6ef8 813f6c58 813cf3d8

kd>

813f6c58 8140c198 813f6ef8

kd>

8140c198 8140cef8 813f6c58

kd>

8140cef8 8140cc58 8140c198

kd>

8140cc58 8140c9b8 8140cef8

kd>

8140c9b8 8140c6b8 8140cc58

kd>

8140c6b8 813f5198 8140c9b8

kd>

813f5198 813f53d8 8140c6b8

kd>

813f53d8 fcccd430 813f5198

kd>

fcccd430 fcccd530 813f53d8

kd>

fcccd530 fcccd610 fcccd430

kd>

fcccd610 813c84b8 fcccd530

kd>

813c84b8 f08915d0 fcccd610

kd>

f08915d0 f0325c10 813c84b8

kd>

f0325c10 f0325a30 f08915d0

kd>

f0325a30 f0325ff0 f0325c10

kd>

f0325ff0 f0325a90 f0325a30

kd>

f0325a90 f0325f70 f0325ff0

kd>

f0325f70 f03260f0 f0325a90

kd>

f03260f0 f03259d0 f0325f70

kd>

f03259d0 8132eb58 f03260f0

kd>

8132eb58 812aa5f0 f03259d0

kd>

812aa5f0 812aa640 8132eb58

kd>

812aa640 812aa690 812aa5f0

kd>

812aa690 812aa6e0 812aa640

kd>

812aa6e0 812aa730 812aa690

kd>

812aa730 812aa780 812aa6e0

kd>

812aa780 f05283f0 812aa730

kd>

f05283f0 f0528450 812aa780

kd>

f0528450 812a7f98 f05283f0

kd>

812a7f98 812a32e8 f0528450

kd>

812a32e8 812a3338 812a7f98

kd>

812a3338 812a50f8 812a32e8

kd>

812a50f8 f05574b0 812a3338

kd>

f05574b0 f05572f0 812a50f8

kd>

f05572f0 f05576b0 f05574b0

kd>

f05576b0 f05573b0 f05572f0

kd>

f05573b0 f0557450 f05576b0

kd>

f0557450 f0557650 f05573b0

kd>

f0557650 f07fd150 f0557450

kd>

f07fd150 f07fd330 f0557650

kd>

f07fd330 ef093848 f07fd150

kd>

ef093848 ef05d910 f07fd330

kd>

ef05d910 810a6b38 ef093848

kd>

810a6b38 810a6b88 ef05d910

kd>

810a6b88 810a6bd8 810a6b38

kd>

810a6bd8 810a6c28 810a6b88

kd>

810a6c28 eeffeb50 810a6bd8

kd>

eeffeb50 eeffebf0 810a6c28

kd>

eeffebf0 eeffeba0 eeffeb50

kd>

eeffeba0 eeffec40 eeffebf0

kd>

eeffec40 eeffec90 eeffeba0

kd>

eeffec90 80473378 eeffec40

kd>

80473378 8047f8d0 eeffec90

// 我们又看到了 80473378 ,表示链已经循环了

LookasideList 的项

LookasideList 的项通过 +00 struct _SINGLE_LIST_ENTRY *Next 的链,链在一起。为空表示链结束。

下面使用 kd 举一个例子。

kd> !lookaside 810eae68

!lookaside 810eae68

Lookaside "" @ 810eae68 "Usqm"

Type = 0021 PagedPool

Current Depth = 4 Max Depth = 4

Size = 48 Max Alloc = 192

AllocateMisses = 922 FreeMisses = 918

TotalAllocates = 56869 TotalFrees = 56869

Hit Rate = 98% Hit Rate = 98%

// 810eae68 处是 PAGED_LOOKASIDE_LIST +0 处的4个字节就是链的开始

kd> dd 810eae68+0 l 1

dd 810eae68+0 l 1

810eae68 e2f44428

// e2f44428 是指向Buf的指针,之前的4个字节是维护该Buf结构中的Tag

// Buf的首地址开始的4个字节用来形成链

kd> db e2f44428-4 l 4 ; dd e2f44428 l 1

db e2f44428-4 l 4 ; dd e2f44428 l 1

e2f44424 55 73 71 6d Usqm

e2f44428 e2fdc2a8

kd> db e2fdc2a8-4 l 4 ; dd e2fdc2a8 l 1

db e2fdc2a8-4 l 4 ; dd e2fdc2a8 l 1

e2fdc2a4 55 73 71 6d Usqm

e2fdc2a8 e13a2c68

kd> db e13a2c68-4 l 4 ; dd e13a2c68 l 1

db e13a2c68-4 l 4 ; dd e13a2c68 l 1

e13a2c64 55 73 71 6d Usqm

e13a2c68 e16d4f88

kd> db e16d4f88-4 l 4 ; dd e16d4f88 l 1

db e16d4f88-4 l 4 ; dd e16d4f88 l 1

e16d4f84 55 73 71 6d Usqm

e16d4f88 00000000

// 我们看到每一个的Tag的确是 Usqm。也看到一共4项,和通过 PAGED_LOOKASIDE_LIST 结构得到的项数是相

// 符的。最后一项为0表示链表结束。

LookasideList 上的申请与释放

跟 ntoskrnl!ExFreeToPagedLookasideList 会发现,会比较 LookasideList 结构+4处的 ListHead.Depth(uint16)和+8处的Depth(uint16),如果 ListHead.Depth 小于 Depth 就会把被free的项插入到链头(将free项的开始4个字节,设为原来的链头,然后把链头的值设为free项的地址)如果大于等于的话,就会用free项地址做参数调用+2c处的free函数。

跟 ntoskrnl!ExAllocateFromPagedLookasideList 会发现,会测试 LookasideList 结构开头的Next是否为空,为空调用+28处的alloc函数申请一块。不为空就把这一块提交。

欢迎交流,欢迎交朋友,

欢迎访问 http://jiurl.yeah.net http://jiurl.cosoft.org.cn/forum

 
 
 
免责声明:本文为网络用户发布,其观点仅代表作者个人观点,与本站无关,本站仅提供信息存储服务。文中陈述内容未经本站证实,其真实性、完整性、及时性本站不作任何保证或承诺,请读者仅作参考,并请自行核实相关内容。
2023年上半年GDP全球前十五强
 百态   2023-10-24
美众议院议长启动对拜登的弹劾调查
 百态   2023-09-13
上海、济南、武汉等多地出现不明坠落物
 探索   2023-09-06
印度或要将国名改为“巴拉特”
 百态   2023-09-06
男子为女友送行,买票不登机被捕
 百态   2023-08-20
手机地震预警功能怎么开?
 干货   2023-08-06
女子4年卖2套房花700多万做美容:不但没变美脸,面部还出现变形
 百态   2023-08-04
住户一楼被水淹 还冲来8头猪
 百态   2023-07-31
女子体内爬出大量瓜子状活虫
 百态   2023-07-25
地球连续35年收到神秘规律性信号,网友:不要回答!
 探索   2023-07-21
全球镓价格本周大涨27%
 探索   2023-07-09
钱都流向了那些不缺钱的人,苦都留给了能吃苦的人
 探索   2023-07-02
倩女手游刀客魅者强控制(强混乱强眩晕强睡眠)和对应控制抗性的关系
 百态   2020-08-20
美国5月9日最新疫情:美国确诊人数突破131万
 百态   2020-05-09
荷兰政府宣布将集体辞职
 干货   2020-04-30
倩女幽魂手游师徒任务情义春秋猜成语答案逍遥观:鹏程万里
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案神机营:射石饮羽
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案昆仑山:拔刀相助
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案天工阁:鬼斧神工
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案丝路古道:单枪匹马
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:与虎谋皮
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:李代桃僵
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:指鹿为马
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案金陵:小鸟依人
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案金陵:千金买邻
 干货   2019-11-12
 
推荐阅读
 
 
 
>>返回首頁<<
 
靜靜地坐在廢墟上,四周的荒凉一望無際,忽然覺得,淒涼也很美
© 2005- 王朝網路 版權所有