驱动开发:内核遍历进程VAD结构体
在上一篇文章《驱动开发:内核中实现Dump进程转储》
中我们实现了ARK工具的转存功能,本篇文章继续以内存为出发点介绍VAD
结构,该结构的全程是Virtual Address Descriptor
即虚拟地址描述符
,VAD是一个AVL
自平衡二叉树
,树的每一个节点代表一段虚拟地址空间。程序中的代码段,数据段,堆段都会各种占用一个或多个VAD
节点,由一个MMVAD
结构完整描述。
VAD结构的遍历效果如下:
那么这个结构在哪?每一个进程都有自己单独的VAD
结构树,这个结构通常在EPROCESS
结构里面里面,在内核调试模式下使用dt _EPROCESS
可得到如下信息。
lyshark.com 1: kd> dt _EPROCESS
ntdll!_EPROCESS+0x500 Vm : _MMSUPPORT_FULL+0x640 MmProcessLinks : _LIST_ENTRY+0x650 ModifiedPageCount : Uint4B+0x654 ExitStatus : Int4B+0x658 VadRoot : _RTL_AVL_TREE+0x660 VadHint : Ptr64 Void+0x668 VadCount : Uint8B+0x670 VadPhysicalPages : Uint8B+0x678 VadPhysicalPagesLimit : Uint8B
可以看到在本系统中VAD的偏移是+0x658
紧跟其后的还有vadCount
的计数等。
VAD结构是如何被添加的?通常情况下系统调用VirtualAllocate
等申请一段堆内存时,则会在VAD树上增加一个结点_MMVAD
结构体,需要说明的是栈并不受VAD的管理。由系统直接分配空间,并把地址记录在了TEB中。
lyshark.com 0: kd> dt _MMVAD
nt!_MMVAD+0x000 Core : _MMVAD_SHORT+0x040 u2 : <anonymous-tag>+0x048 Subsection : Ptr64 _SUBSECTION+0x050 FirstPrototypePte : Ptr64 _MMPTE+0x058 LastContiguousPte : Ptr64 _MMPTE+0x060 ViewLinks : _LIST_ENTRY+0x070 VadsProcess : Ptr64 _EPROCESS+0x078 u4 : <anonymous-tag>+0x080 FileObject : Ptr64 _FILE_OBJECT
结构体MMVAD
则是每一个VAD
内存块的属性,这个内存结构定义在WinDBG中可看到。
如上在EPROCESS
结构中可以找到VAD结构的相对偏移+0x658
以及进程VAD计数偏移+0x668
,我们首先通过!process 0 0
指令得到当前所有进程的EPROCESS
结构,并选中进程。
lyshark.com 0: kd> !process 0 0
PROCESS ffffe28fbb0860c0SessionId: 1 Cid: 11a8 Peb: 0035c000 ParentCid: 11c8DirBase: 309f3002 ObjectTable: ffffac87ba3da580 HandleCount: 145.Image: x64.exe
此处的ffffe28fbb0860c0
正是我们所需要的EPROCESS
结构。
当需要得到该进程的VAD结构时,只需要使用!vad ffffe28fbb0860c0 + 0x658
来显示该进程的VAD树。
至于获取VAD有多少条,则可以直接使用!vad ffffe28fbb0860c0 + 0x668
来获取到。
既然手动可以遍历出来,那么自动化也并不难,首先定义头文件vad.h
同样这是微软定义,如果想要的到最新的,自己下载WinDBG调试内核输入命令。
#pragma once
#include <ntifs.h>typedef struct _MM_GRAPHICS_VAD_FLAGS // 15 elements, 0x4 bytes (sizeof)
{/*0x000*/ ULONG32 Lock : 1; // 0 BitPosition /*0x000*/ ULONG32 LockContended : 1; // 1 BitPosition /*0x000*/ ULONG32 DeleteInProgress : 1; // 2 BitPosition /*0x000*/ ULONG32 NoChange : 1; // 3 BitPosition /*0x000*/ ULONG32 VadType : 3; // 4 BitPosition /*0x000*/ ULONG32 Protection : 5; // 7 BitPosition /*0x000*/ ULONG32 PreferredNode : 6; // 12 BitPosition /*0x000*/ ULONG32 PageSize : 2; // 18 BitPosition /*0x000*/ ULONG32 PrivateMemoryAlwaysSet : 1; // 20 BitPosition /*0x000*/ ULONG32 WriteWatch : 1; // 21 BitPosition /*0x000*/ ULONG32 FixedLargePageSize : 1; // 22 BitPosition /*0x000*/ ULONG32 ZeroFillPagesOptional : 1; // 23 BitPosition /*0x000*/ ULONG32 GraphicsAlwaysSet : 1; // 24 BitPosition /*0x000*/ ULONG32 GraphicsUseCoherentBus : 1; // 25 BitPosition /*0x000*/ ULONG32 GraphicsPageProtection : 3; // 26 BitPosition
}MM_GRAPHICS_VAD_FLAGS, *PMM_GRAPHICS_VAD_FLAGS;
typedef struct _MM_PRIVATE_VAD_FLAGS // 15 elements, 0x4 bytes (sizeof)
{/*0x000*/ ULONG32 Lock : 1; // 0 BitPosition /*0x000*/ ULONG32 LockContended : 1; // 1 BitPosition /*0x000*/ ULONG32 DeleteInProgress : 1; // 2 BitPosition /*0x000*/ ULONG32 NoChange : 1; // 3 BitPosition /*0x000*/ ULONG32 VadType : 3; // 4 BitPosition /*0x000*/ ULONG32 Protection : 5; // 7 BitPosition /*0x000*/ ULONG32 PreferredNode : 6; // 12 BitPosition /*0x000*/ ULONG32 PageSize : 2; // 18 BitPosition /*0x000*/ ULONG32 PrivateMemoryAlwaysSet : 1; // 20 BitPosition /*0x000*/ ULONG32 WriteWatch : 1; // 21 BitPosition /*0x000*/ ULONG32 FixedLargePageSize : 1; // 22 BitPosition /*0x000*/ ULONG32 ZeroFillPagesOptional : 1; // 23 BitPosition /*0x000*/ ULONG32 Graphics : 1; // 24 BitPosition /*0x000*/ ULONG32 Enclave : 1; // 25 BitPosition /*0x000*/ ULONG32 ShadowStack : 1; // 26 BitPosition
}MM_PRIVATE_VAD_FLAGS, *PMM_PRIVATE_VAD_FLAGS;typedef struct _MMVAD_FLAGS // 9 elements, 0x4 bytes (sizeof)
{/*0x000*/ ULONG32 Lock : 1; // 0 BitPosition /*0x000*/ ULONG32 LockContended : 1; // 1 BitPosition /*0x000*/ ULONG32 DeleteInProgress : 1; // 2 BitPosition /*0x000*/ ULONG32 NoChange : 1; // 3 BitPosition /*0x000*/ ULONG32 VadType : 3; // 4 BitPosition /*0x000*/ ULONG32 Protection : 5; // 7 BitPosition /*0x000*/ ULONG32 PreferredNode : 6; // 12 BitPosition /*0x000*/ ULONG32 PageSize : 2; // 18 BitPosition /*0x000*/ ULONG32 PrivateMemory : 1; // 20 BitPosition
}MMVAD_FLAGS, *PMMVAD_FLAGS;typedef struct _MM_SHARED_VAD_FLAGS // 11 elements, 0x4 bytes (sizeof)
{/*0x000*/ ULONG32 Lock : 1; // 0 BitPosition /*0x000*/ ULONG32 LockContended : 1; // 1 BitPosition /*0x000*/ ULONG32 DeleteInProgress : 1; // 2 BitPosition /*0x000*/ ULONG32 NoChange : 1; // 3 BitPosition /*0x000*/ ULONG32 VadType : 3; // 4 BitPosition /*0x000*/ ULONG32 Protection : 5; // 7 BitPosition /*0x000*/ ULONG32 PreferredNode : 6; // 12 BitPosition /*0x000*/ ULONG32 PageSize : 2; // 18 BitPosition /*0x000*/ ULONG32 PrivateMemoryAlwaysClear : 1; // 20 BitPosition /*0x000*/ ULONG32 PrivateFixup : 1; // 21 BitPosition /*0x000*/ ULONG32 HotPatchAllowed : 1; // 22 BitPosition
}MM_SHARED_VAD_FLAGS, *PMM_SHARED_VAD_FLAGS;typedef struct _MMVAD_FLAGS2 // 7 elements, 0x4 bytes (sizeof)
{/*0x000*/ ULONG32 FileOffset : 24; // 0 BitPosition /*0x000*/ ULONG32 Large : 1; // 24 BitPosition /*0x000*/ ULONG32 TrimBehind : 1; // 25 BitPosition /*0x000*/ ULONG32 Inherit : 1; // 26 BitPosition /*0x000*/ ULONG32 NoValidationNeeded : 1; // 27 BitPosition /*0x000*/ ULONG32 PrivateDemandZero : 1; // 28 BitPosition /*0x000*/ ULONG32 Spare : 3; // 29 BitPosition
}MMVAD_FLAGS2, *PMMVAD_FLAGS2;typedef struct _MMVAD_SHORT
{RTL_BALANCED_NODE VadNode;UINT32 StartingVpn; /*0x18*/UINT32 EndingVpn; /*0x01C*/UCHAR StartingVpnHigh;UCHAR EndingVpnHigh;UCHAR CommitChargeHigh;UCHAR SpareNT64VadUChar;INT32 ReferenceCount;EX_PUSH_LOCK PushLock; /*0x028*/struct{union{ULONG_PTR flag;MM_PRIVATE_VAD_FLAGS PrivateVadFlags; /*0x030*/MMVAD_FLAGS VadFlags;MM_GRAPHICS_VAD_FLAGS GraphicsVadFlags;MM_SHARED_VAD_FLAGS SharedVadFlags;}Flags;}u1;PVOID EventList; /*0x038*/}MMVAD_SHORT, *PMMVAD_SHORT;typedef struct _MMADDRESS_NODE
{ULONG64 u1;struct _MMADDRESS_NODE* LeftChild;struct _MMADDRESS_NODE* RightChild;ULONG64 StartingVpn;ULONG64 EndingVpn;
}MMADDRESS_NODE, *PMMADDRESS_NODE;typedef struct _MMEXTEND_INFO // 2 elements, 0x10 bytes (sizeof)
{/*0x000*/ UINT64 CommittedSize;/*0x008*/ ULONG32 ReferenceCount;/*0x00C*/ UINT8 _PADDING0_[0x4];
}MMEXTEND_INFO, *PMMEXTEND_INFO;
struct _SEGMENT
{struct _CONTROL_AREA* ControlArea;ULONG TotalNumberOfPtes;ULONG SegmentFlags;ULONG64 NumberOfCommittedPages;ULONG64 SizeOfSegment;union{struct _MMEXTEND_INFO* ExtendInfo;void* BasedAddress;}u;ULONG64 SegmentLock;ULONG64 u1;ULONG64 u2;PVOID* PrototypePte;ULONGLONG ThePtes[0x1];
};typedef struct _EX_FAST_REF
{union{PVOID Object;ULONG_PTR RefCnt : 3;ULONG_PTR Value;};
} EX_FAST_REF, *PEX_FAST_REF;typedef struct _CONTROL_AREA // 17 elements, 0x80 bytes (sizeof)
{/*0x000*/ struct _SEGMENT* Segment;union // 2 elements, 0x10 bytes (sizeof) {/*0x008*/ struct _LIST_ENTRY ListHead; // 2 elements, 0x10 bytes (sizeof) /*0x008*/ VOID* AweContext;};/*0x018*/ UINT64 NumberOfSectionReferences;/*0x020*/ UINT64 NumberOfPfnReferences;/*0x028*/ UINT64 NumberOfMappedViews;/*0x030*/ UINT64 NumberOfUserReferences;/*0x038*/ ULONG32 u; // 2 elements, 0x4 bytes (sizeof) /*0x03C*/ ULONG32 u1; // 2 elements, 0x4 bytes (sizeof) /*0x040*/ struct _EX_FAST_REF FilePointer; // 3 elements, 0x8 bytes (sizeof) // 4 elements, 0x8 bytes (sizeof)
}CONTROL_AREA, *PCONTROL_AREA;typedef struct _SUBSECTION_
{struct _CONTROL_AREA* ControlArea;}SUBSECTION, *PSUBSECTION;typedef struct _MMVAD
{MMVAD_SHORT Core;union /*0x040*/{UINT32 LongFlags2;//现在用不到省略MMVAD_FLAGS2 VadFlags2;}u2;PSUBSECTION Subsection; /*0x048*/PVOID FirstPrototypePte; /*0x050*/PVOID LastContiguousPte; /*0x058*/LIST_ENTRY ViewLinks; /*0x060*/PEPROCESS VadsProcess; /*0x070*/PVOID u4; /*0x078*/PVOID FileObject; /*0x080*/
}MMVAD, *PMMVAD;typedef struct _RTL_AVL_TREE // 1 elements, 0x8 bytes (sizeof)
{/*0x000*/ struct _RTL_BALANCED_NODE* Root;
}RTL_AVL_TREE, *PRTL_AVL_TREE;typedef struct _VAD_INFO_
{ULONG_PTR pVad;ULONG_PTR startVpn;ULONG_PTR endVpn;ULONG_PTR pFileObject;ULONG_PTR flags;
}VAD_INFO, *PVAD_INFO;typedef struct _ALL_VADS_
{ULONG nCnt;VAD_INFO VadInfos[1];
}ALL_VADS, *PALL_VADS;typedef struct _MMSECTION_FLAGS // 27 elements, 0x4 bytes (sizeof)
{/*0x000*/ UINT32 BeingDeleted : 1; // 0 BitPosition /*0x000*/ UINT32 BeingCreated : 1; // 1 BitPosition /*0x000*/ UINT32 BeingPurged : 1; // 2 BitPosition /*0x000*/ UINT32 NoModifiedWriting : 1; // 3 BitPosition /*0x000*/ UINT32 FailAllIo : 1; // 4 BitPosition /*0x000*/ UINT32 Image : 1; // 5 BitPosition /*0x000*/ UINT32 Based : 1; // 6 BitPosition /*0x000*/ UINT32 File : 1; // 7 BitPosition /*0x000*/ UINT32 AttemptingDelete : 1; // 8 BitPosition /*0x000*/ UINT32 PrefetchCreated : 1; // 9 BitPosition /*0x000*/ UINT32 PhysicalMemory : 1; // 10 BitPosition /*0x000*/ UINT32 ImageControlAreaOnRemovableMedia : 1; // 11 BitPosition /*0x000*/ UINT32 Reserve : 1; // 12 BitPosition /*0x000*/ UINT32 Commit : 1; // 13 BitPosition /*0x000*/ UINT32 NoChange : 1; // 14 BitPosition /*0x000*/ UINT32 WasPurged : 1; // 15 BitPosition /*0x000*/ UINT32 UserReference : 1; // 16 BitPosition /*0x000*/ UINT32 GlobalMemory : 1; // 17 BitPosition /*0x000*/ UINT32 DeleteOnClose : 1; // 18 BitPosition /*0x000*/ UINT32 FilePointerNull : 1; // 19 BitPosition /*0x000*/ ULONG32 PreferredNode : 6; // 20 BitPosition /*0x000*/ UINT32 GlobalOnlyPerSession : 1; // 26 BitPosition /*0x000*/ UINT32 UserWritable : 1; // 27 BitPosition /*0x000*/ UINT32 SystemVaAllocated : 1; // 28 BitPosition /*0x000*/ UINT32 PreferredFsCompressionBoundary : 1; // 29 BitPosition /*0x000*/ UINT32 UsingFileExtents : 1; // 30 BitPosition /*0x000*/ UINT32 PageSize64K : 1; // 31 BitPosition
}MMSECTION_FLAGS, *PMMSECTION_FLAGS;typedef struct _SECTION // 9 elements, 0x40 bytes (sizeof)
{/*0x000*/ struct _RTL_BALANCED_NODE SectionNode; // 6 elements, 0x18 bytes (sizeof) /*0x018*/ UINT64 StartingVpn;/*0x020*/ UINT64 EndingVpn;/*0x028*/ union {PCONTROL_AREA ControlArea;PVOID FileObject;}u1; // 4 elements, 0x8 bytes (sizeof) /*0x030*/ UINT64 SizeOfSection;/*0x038*/ union {ULONG32 LongFlags;MMSECTION_FLAGS Flags;}u; // 2 elements, 0x4 bytes (sizeof) struct // 3 elements, 0x4 bytes (sizeof) {/*0x03C*/ ULONG32 InitialPageProtection : 12; // 0 BitPosition /*0x03C*/ ULONG32 SessionId : 19; // 12 BitPosition /*0x03C*/ ULONG32 NoValidationNeeded : 1; // 31 BitPosition };
}SECTION, *PSECTION;
引入vad.h
头文件,并写入如下代码,此处的eprocess_offset_VadRoot
以及eprocess_offset_VadCount
则是上方得出的相对于EPROCESS
结构的偏移值,每个系统都不一样,版本不同偏移值会不同。
#include "vad.h"
#include <ntifs.h>// 定义VAD相对于EProcess头部偏移值
#define eprocess_offset_VadRoot 0x658
#define eprocess_offset_VadCount 0x668VOID EnumVad(PMMVAD Root, PALL_VADS pBuffer, ULONG nCnt)
{if (!Root || !pBuffer || !nCnt){return;}__try{if (nCnt > pBuffer->nCnt){// 得到起始页与结束页ULONG64 endptr = (ULONG64)Root->Core.EndingVpnHigh;endptr = endptr << 32;ULONG64 startptr = (ULONG64)Root->Core.StartingVpnHigh;startptr = startptr << 32;// 得到根节点pBuffer->VadInfos[pBuffer->nCnt].pVad = (ULONG_PTR)Root;// 起始页: startingVpn * 0x1000pBuffer->VadInfos[pBuffer->nCnt].startVpn = (startptr | Root->Core.StartingVpn) << PAGE_SHIFT;// 结束页: EndVpn * 0x1000 + 0xfffpBuffer->VadInfos[pBuffer->nCnt].endVpn = ((endptr | Root->Core.EndingVpn) << PAGE_SHIFT) + 0xfff;// VAD标志 928 = Mapped 1049088 = Private ....pBuffer->VadInfos[pBuffer->nCnt].flags = Root->Core.u1.Flags.flag;// 验证节点可读性if (MmIsAddressValid(Root->Subsection) && MmIsAddressValid(Root->Subsection->ControlArea)){if (MmIsAddressValid((PVOID)((Root->Subsection->ControlArea->FilePointer.Value >> 4) << 4))){pBuffer->VadInfos[pBuffer->nCnt].pFileObject = ((Root->Subsection->ControlArea->FilePointer.Value >> 4) << 4);}}pBuffer->nCnt++;}if (MmIsAddressValid(Root->Core.VadNode.Left)){// 递归枚举左子树EnumVad((PMMVAD)Root->Core.VadNode.Left, pBuffer, nCnt);}if (MmIsAddressValid(Root->Core.VadNode.Right)){// 递归枚举右子树EnumVad((PMMVAD)Root->Core.VadNode.Right, pBuffer, nCnt);}}__except (1){}
}BOOLEAN EnumProcessVad(ULONG Pid, PALL_VADS pBuffer, ULONG nCnt)
{PEPROCESS Peprocess = 0;PRTL_AVL_TREE Table = NULL;PMMVAD Root = NULL;// 通过进程PID得到进程EProcessif (NT_SUCCESS(PsLookupProcessByProcessId((HANDLE)Pid, &Peprocess))){// 与偏移相加得到VAD头节点Table = (PRTL_AVL_TREE)((UCHAR*)Peprocess + eprocess_offset_VadRoot);if (!MmIsAddressValid(Table) || !eprocess_offset_VadRoot){return FALSE;}__try{// 取出头节点Root = (PMMVAD)Table->Root;if (nCnt > pBuffer->nCnt){// 得到起始页与结束页ULONG64 endptr = (ULONG64)Root->Core.EndingVpnHigh;endptr = endptr << 32;ULONG64 startptr = (ULONG64)Root->Core.StartingVpnHigh;startptr = startptr << 32;pBuffer->VadInfos[pBuffer->nCnt].pVad = (ULONG_PTR)Root;// 起始页: startingVpn * 0x1000pBuffer->VadInfos[pBuffer->nCnt].startVpn = (startptr | Root->Core.StartingVpn) << PAGE_SHIFT;// 结束页: EndVpn * 0x1000 + 0xfffpBuffer->VadInfos[pBuffer->nCnt].endVpn = (endptr | Root->Core.EndingVpn) << PAGE_SHIFT;pBuffer->VadInfos[pBuffer->nCnt].flags = Root->Core.u1.Flags.flag;if (MmIsAddressValid(Root->Subsection) && MmIsAddressValid(Root->Subsection->ControlArea)){if (MmIsAddressValid((PVOID)((Root->Subsection->ControlArea->FilePointer.Value >> 4) << 4))){pBuffer->VadInfos[pBuffer->nCnt].pFileObject = ((Root->Subsection->ControlArea->FilePointer.Value >> 4) << 4);}}pBuffer->nCnt++;}// 枚举左子树if (Table->Root->Left){EnumVad((MMVAD*)Table->Root->Left, pBuffer, nCnt);}// 枚举右子树if (Table->Root->Right){EnumVad((MMVAD*)Table->Root->Right, pBuffer, nCnt);}}__finally{ObDereferenceObject(Peprocess);}}else{return FALSE;}return TRUE;
}VOID UnDriver(PDRIVER_OBJECT driver)
{DbgPrint(("Uninstall Driver Is OK \n"));
}NTSTATUS DriverEntry(IN PDRIVER_OBJECT Driver, PUNICODE_STRING RegistryPath)
{DbgPrint(("hello lyshark \n"));typedef struct{ULONG nPid;ULONG nSize;PALL_VADS pBuffer;}VADProcess;__try{VADProcess vad = { 0 };vad.nPid = 4520;// 默认有1000个线程vad.nSize = sizeof(VAD_INFO) * 0x5000 + sizeof(ULONG);// 分配临时空间vad.pBuffer = (PALL_VADS)ExAllocatePool(PagedPool, vad.nSize);// 根据传入长度得到枚举数量ULONG nCount = (vad.nSize - sizeof(ULONG)) / sizeof(VAD_INFO);// 枚举VADEnumProcessVad(vad.nPid, vad.pBuffer, nCount);// 输出VADfor (size_t i = 0; i < vad.pBuffer->nCnt; i++){DbgPrint("StartVPN = %p | ", vad.pBuffer->VadInfos[i].startVpn);DbgPrint("EndVPN = %p | ", vad.pBuffer->VadInfos[i].endVpn);DbgPrint("PVAD = %p | ", vad.pBuffer->VadInfos[i].pVad);DbgPrint("Flags = %d | ", vad.pBuffer->VadInfos[i].flags);DbgPrint("pFileObject = %p \n", vad.pBuffer->VadInfos[i].pFileObject);}}__except (1){}Driver->DriverUnload = UnDriver;return STATUS_SUCCESS;
}
程序运行后输出效果如下:
驱动开发:内核遍历进程VAD结构体相关推荐
- 鸿蒙系统深度解析,深度解析鸿蒙内核最重要的结构体
谁是鸿蒙内核最重要的结构体? 答案一定是:LOS_DL_LIST(双向链表),它长这样. typedef struct LOS_DL_LIST {//双向链表,内核最重要结构体 struct LOS_ ...
- Linux驱动开发—内核I2C驱动详解
Linux驱动开发--内核I2C驱动 I2C驱动文件结构 I2C数据传输过程 i2c_transfer i2c_msg I2C通讯常用的接口函数(老版本) 快速读写接口函数:(连续读写) 常用的读操作 ...
- Window XP驱动开发(十) 驱动程序的基本结构
转载请标明是引用于 http://blog.csdn.net/chenyujing1234 欢迎大家提出意见,一起讨论! 参考书籍<<Windows驱动开发技术详解>> 一.数 ...
- 如何在内核里面查找某些结构体或者宏的定义
想要查看一些结构体的定义,比如struct ip_mreq,可以查看头文件,所有的系统预定义的结构体都在内核源代码的/include下有定义,ubuntu里面是/usr/include . 比如要找 ...
- linux进程内存结构体,Linux下网络编程(3)——进程间通信(IPC),共享内存,传递结构体数据...
1. 前言 多进程,总有一些交互要做,不可能各自独立. 这里是最简单的例子.一个写入,一个读取. 一个建立共享内存,写入数据. 一个读取共享内存的内容. 2. 简单例子代码 twriter.cpp 代 ...
- linux内核网络协议栈--sk_buff结构体(四)
一.struct sk_buff struct sk_buff {/* These two members must be first. */struct sk_buff *next;struct s ...
- Linux 内核网络协议栈 ------sk_buff 结构体 以及 完全解释 (2.6.16)
在2.6.24之后这个结构体有了较大的变化,此处先说一说2.6.16版本的sk_buff,以及解释一些问题. 一. 先直观的看一下这个结构体~~~~~~~~~~~~~~~~~~~~~~在下面解释每个字 ...
- VC跨进程数据(结构体)传递-WM_COPYDATA
两个测试程序,都是MFC基于对话框的应用程序,一个是发送者,一个是接收者. 两个程序都使用同一个结构体: typedef struct {char imsi[20];char options[512] ...
- 嵌入式C开发中用到的位域结构体
一.位域描述 存放一个开关量或者其他开关状态时,用一位二进位即可.为了减少嵌入式内存资源的开销,可以使用位域进行定义,位域是C语言支持的一种数据结构,称为"位域"或"位段 ...
- 嵌入式软件开发培训笔记——C高级 结构体与共用体
(1).结构体 基本类型 int.double.char.float.short.long等等 复合类型 数组.结构体 指针类型 空类型 1)定义结构体,不会在内存内给分配空间 ...
最新文章
- pandas drop 删除行和列的方法
- 利用onSaveInstanceState()方法保存Activity状态
- [原]软件设计的一些感悟
- 美国版“非升即走”瞄准终身教授,2年评审不通过就减薪撤职,其他高校开始抢人...
- python入门到实践-Python编程从入门到实践(基础入门)
- 关于CSS3实现响应式布局的一些概念和术语
- shiro学习(15):使用注解实现权限认证和后台管理
- c#官方推荐md5通用加密类
- 常用报文的解析与相互转换
- HTK下yes/no的识别
- 20181031-1
- 送给年轻人创业的经典好文章
- Python编程语言中获取操作系统进程信息的方法
- 3.3.7 使用difflib.get_close_matches函数
- decklink linux 驱动下载,Blackmagic Design DeckLink采集卡驱动
- Tera Term 下载教程
- 计算机无法加入域请确保域名,处理计算机无法加入域的错误一则Server2008
- ThinkPHP6项目基操目录
- SP_Flash_Tool对应MTK CPU型号速查表汇总分析
- controller(控制器)