问题描述:
在64位平台开发32位程序,用户态32位程序传递一个结构给内核64位驱动。
用户态32bit
typedef struct _COMMAND_MESSAGE {
ULONG ID;
union {
CHAR value[1];
HANDLE handle;
};
} MSG,*PMSG;
内核态 64 bit:
typedef struct _COMMAND_MESSAGE {
ULONG ID;
union {
CHAR value[1];
HANDLE handle;
};
} MSG,*PMSG;
内核态接收到msg,请问内核态msg.handle等于多少?
答案:0
解答:请看32bit和64bit的字宽对比如表:
类型
32bit
64bit
char
1
1
Short
2
2
int
4
4
long
4
8
float
4
8
Long long
8
8
double
8
8
Long double
12
16
Void *
4
8
因此,内核态的handle偏移量为8,而用户态偏移量为4。这就涉及到了字节对齐知识了(假设都设定为vs默认8字节对齐)。
解法一:将ULONG ID改成32bit和64bit无差别类型short
Wrong:发现用户态handle偏移量为4,而内核态还是8。因为union结构体用户态对齐4,而内核态对齐8.
对齐口诀如下:
基本类型:对齐如上表
联合体:取最大类型
结构体:每个单元类型对齐
宏观上,类型对齐和系统设置取小值
我的做法是:ID的类型ULONG改成LONG64,或者
typedef struct _COMMAND_MESSAGE {
USHORT ID;
union {
CHAR value[1];
HANDLE handle;
LONG64 reserved;
};
} MSG,*PMSG;
用户态和内核态交互,wdk建议的方法是用户态创建事件对象,传递事件对象句柄。但是开发之初,内核态接收到的句柄永远是NULL,困惑之余挂上windbg,内存值确实是正确的,但是内核msg.handle还是空,猜测是字节对齐问题,查看变量偏移,证实了。然后开始对齐字节,Done!