| 注册
home doc ppt pdf
请输入搜索内容

热门搜索

年终总结个人简历事迹材料租赁合同演讲稿项目管理职场社交

$GetMessage-PeekMessage-SendMessage内核解析

奋斗不止500年

贡献于2021-07-11

字数:28679

忙公司项目(毕设吧)发现长时间没总结该换换脑子
什没SendThreadMessage呢?问题时实现程序逻辑中具体场景中样初学者说喜欢通windwos消息机制完成UI线程worker线程间步通信号量做问题直困惑久现搞明白
google问题牛(Raymond Chen)httpblogsmsdncomboldnewthingarchive200812239248851aspx)博客中提引发讨里简单翻译Raymond Chen法
想象中SendThreadMessage工作呢?调SendMessage 消息直接分发窗口程?没消息泵想象中SendThreadMessage会消息分发谁呢?没thread window procedure’样东东处理消息
线程中做消息泵想象中SendThreadMessage需等消息处理完毕够知道消息处理完毕?等DispatchMessage返回DispatchMessage失败知道应该窗口分发消息window manager线程发送消息仅已
会认等知道GetMessage or PeekMessage样确定消息解决保证消息检索函数(GetMessage PeekMessage)前消息泵线程消息启动模态窗口消息检索函数告诉消息已处理完毕事实模态窗口创建消息泵
段然长头GetMessage   DispatchMessage2基函数天天行知甚少算第次写HelloWorld 现少1年然朦胧感十分惭愧篇总结做确庞工程解2函数需握windows消息机制windwos 没源代码参考里参考ReactOS实现然windows正统应该差远少win2003相似开始步入正题
首先需解UI线程 普通Worker线程间区什
msdn httpmsdnmicrosoftcomenuslibraryms644927提:
To avoid the overhead of creating a message queue for non–GUI threads all threads are created initially without a message queue The system creates a threadspecific message queue only when the thread makes its first call to one of the specific user functions no GUI function calls result in the creation of a message queue
然系统创建线程时普通non–GUI thread直GDI User函数调线程创建消息队列函数调开始
windwos开始时linux样 图形部分户空间中进程负责面减少进程间环境切换放入核中系统调层2种情况种调原核调种新加进原户空间调部分称扩充系统调部分代码放动态安装模块win32ksys应系统调表2包括前核系统调前基础增加图形图系统调系统调发现扩充系统调时原表满足求windwos会会扩充系统调表装载win32ksys模块普普通通线程开始变GUI线程
激动心旅程里开始
开源代码意够贴出
NTSTATUS
NTAPI
PsConvertToGuiThread(VOID)
{
ULONG_PTR NewStack
PVOID OldStack
PETHREAD Thread PsGetCurrentThread()
PEPROCESS Process PsGetCurrentProcess()
NTSTATUS Status
PAGED_CODE()

* Validate the previous mode *
if (KeGetPreviousMode() KernelMode) return STATUS_INVALID_PARAMETER

* If no win32k crashes later *
ASSERT(PspW32ProcessCallout NULL)

* Make sure win32k is here *
if (PspW32ProcessCallout) return STATUS_ACCESS_DENIED

* Make sure it's not already win32 *
if (Thread>TcbServiceTable KeServiceDescriptorTable)
{
* We're already a win32 thread *
return STATUS_ALREADY_WIN32
}

* Check if we don't already have a kernelmode stack *
if (Thread>TcbLargeStack)
{
* We don't create one *
NewStack (ULONG_PTR)MmCreateKernelStack(TRUE 0)
if (NewStack)
{
* Panic in usermode *
NtCurrentTeb()>LastErrorValue ERROR_NOT_ENOUGH_MEMORY
return STATUS_NO_MEMORY
}

* We're about to switch stacks Enter a guarded region *
KeEnterGuardedRegion()

* Switch stacks *
OldStack KeSwitchKernelStack((PVOID)NewStack
(PVOID)(NewStack KERNEL_STACK_SIZE))

* Leave the guarded region *
KeLeaveGuardedRegion()

* Delete the old stack *
MmDeleteKernelStack(OldStack FALSE)
}

* This check is bizare Check out win32k later *
if (Process>Win32Process)
{
* Now tell win32k about us *
Status PspW32ProcessCallout(Process TRUE)
if (NT_SUCCESS(Status)) return Status
}

* Set the new service table *
Thread>TcbServiceTable KeServiceDescriptorTableShadow
ASSERT(Thread>TcbWin32Thread 0)

* Tell Win32k about our thread *
Status PspW32ThreadCallout(Thread PsW32ThreadCalloutInitialize)
if (NT_SUCCESS(Status))
{
* Revert our table *
Thread>TcbServiceTable KeServiceDescriptorTable
}

* Return status *
return Status
}

前没提里判断线程system stackGUI线程普通线程增加更嵌套调需更system stackMmCreateKernelStack分配空间函数里分配64K普通thread system stack12K然惯例里64K堆栈提交中12K设置guard page超12K产生异常然分配空间进程果线程GUI线程进程GUI 进程果GUI进程然先进程转PspW32ProcessCallout函数指针指Win32kProcessCallback里干会初始化系列结构体键盘格式GDI 句柄表等等里略细节
系统ServiceTable换成表PspW32ThreadCallout指Win32kThreadCallback里完成普通线程转换成GUI线程程操作系统复杂东东说初始化结构体真茫茫里关注点Win32kThreadCallback中找创建消息队列入口Win32Thread>MessageQueue MsqCreateMessageQueue(Thread)
系统消息队列构成真正win32应程序开发者需窗口程序中构造简单Message DumpGetMessage底做什
GetMessage会调NtUserGetMessage
BOOL APIENTRY
NtUserGetMessage(PMSG pMsg
HWND hWnd
UINT MsgFilterMin
UINT MsgFilterMax )
{
MSG Msg
BOOL Ret

if ( (MsgFilterMin|MsgFilterMax) & ~WM_MAXIMUM )
{
EngSetLastError(ERROR_INVALID_PARAMETER)
return FALSE
}

UserEnterExclusive()

RtlZeroMemory(&Msg sizeof(MSG))

Ret co_IntGetPeekMessage(&Msg hWnd MsgFilterMin MsgFilterMax PM_REMOVE TRUE)

UserLeave()

if (Ret)
{
_SEH2_TRY
{
ProbeForWrite(pMsg sizeof(MSG) 1)
RtlCopyMemory(pMsg &Msg sizeof(MSG))
}
_SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
{
SetLastNtError(_SEH2_GetExceptionCode())
Ret FALSE
}
_SEH2_END
}

return Ret
}

原谅略茫茫细节
BOOL FASTCALL
co_IntGetPeekMessage( PMSG pMsg
HWND hWnd
UINT MsgFilterMin
UINT MsgFilterMax
UINT RemoveMsg
BOOL bGMSG )
{

do
{
Present co_IntPeekMessage( pMsg
Window
MsgFilterMin
MsgFilterMax
RemoveMsg
bGMSG )
if (Present)
{
* GetMessage or PostMessage must never get messages that contain pointers *
ASSERT(FindMsgMemory(pMsg>message) NULL)

if (pMsg>message WM_PAINT && pMsg>message WM_QUIT)
{
pti>timeLast pMsg>time
pti>ptLast pMsg>pt
}

The WH_GETMESSAGE hook enables an application to monitor messages about to
be returned by the GetMessage or PeekMessage function

co_HOOK_CallHooks( WH_GETMESSAGE HC_ACTION RemoveMsg & PM_REMOVE (LPARAM)pMsg)

if ( bGMSG )
{
Present (WM_QUIT pMsg>message)
break
}
}

if ( bGMSG )
{
if ( co_IntWaitMessage(Window MsgFilterMin MsgFilterMax) )
{
Present 1
break
}
}
else
{
if ((RemoveMsg & PM_NOYIELD))
{
IdlePing()
Yield this thread
UserLeave()
ZwYieldExecution()
UserEnterExclusive()
Fall through to exit
IdlePong()
}
break
}
}
while( bGMSG && Present )

Been spinning time to swap vinyl
if (pti>pClientInfo>cSpins > 100)
{
Clear the spin cycle to fix the mix
pti>pClientInfo>cSpins 0
if ((pti>TIF_flags & TIF_SPINNING)) FIXME need to swap vinyl
}
return Present
}

IntGetPeekMessage循环断调co_IntPeekMessage 消息队列中取出消息果没消息调co_IntWaitMessage等消息然复非遇WM_QUIT
co_IntPeekMessage 实现关键PeekMessage关键部分样略繁琐细节然指重实太函数整消息机制核心部分需慢慢
说知道消息队列啥模样
typedef struct _USER_MESSAGE_QUEUE
{
* Reference counter only access this variable with interlocked functions *
LONG References

* Owner of the message queue *
struct _ETHREAD *Thread
* Queue of messages sent to the queue *
LIST_ENTRY SentMessagesListHead 发送消息队列
* Queue of messages posted to the queue *
LIST_ENTRY PostedMessagesListHead Post消息队列
* Queue for hardware messages for the queue *
LIST_ENTRY HardwareMessagesListHead 硬件消息队列



* messages that are currently dispatched by other threads *
LIST_ENTRY DispatchingMessagesHead 已发送方尚未处理消息队列
* messages that are currently dispatched by this message queue required for cleanup *
LIST_ENTRY LocalDispatchingMessagesHead 正分发消息队列



} USER_MESSAGE_QUEUE *PUSER_MESSAGE_QUEUE
SentMessagesListHead 队列东西发送消息队列消息 方调SendMessage消息队列时消息会放队列中
PostedMessagesListHead 理方调PostMessage然消息放队列中
PostMessage函数较容易实现需挂目标PostedMessagesListHead队列中SendMessage复杂
果发送方接收方线程中SendMessage会直接调窗口窗口程函数处理消息
果发送方接收方线程中发送方必须等接收方运行结果继续执行形成感觉步程感觉似复杂简单线程步问题
想问题GUI线程AGUI线程B发送消息时线程B处理A消息时需线程A发送消息2线程会死锁? 然会知道windwos搞套构造完整消息驱动机制更抽象讲消息机制算线程通信机制套东东复杂东东需户程序结合起真正运行起说应程序必须符合windwos程序规范windwos消息机制参起参中重东东前提GetMessageDispatchingMessagesHead LocalDispatchingMessagesHead 实现套机制中非常重部分
DispatchingMessagesHead  SendMessage方时消息需等面结果需等消息放置里里会windwos菜鸟觉困惑困惑什够形成队列呢?里先问题留
站接受者消息队列角度SendMessage需里处理Message Dispatch搞出消息返回值时接受方必须等面消息返回值走消息算搞定里线程甚进程间数传递东西必须考虑消息放里呢?LocalDispatchingMessagesHead 跳出解决问题
总说SendMessage消息时会挂接收方SentMessagesListHead队列中挂发送方DispatchingMessagesHead
接受方先查SentMessagesListHead 否消息话SendMessageListHead中删掉添加LocalDispatchingMessagesHead队列中等消息处理完毕LocalDispatchingMessagesHead消息删
首先关注4队列硬件队列鼠标键盘东东
第次点晕急笼统概念细节部分非常复杂
*
* Internal version of PeekMessage() doing all the work
*
BOOL FASTCALL
co_IntPeekMessage( PMSG Msg
PWND Window
UINT MsgFilterMin
UINT MsgFilterMax
UINT RemoveMsg
BOOL bGMSG )
{

do
{

* Dispatch sent messages here *
while ( co_MsqDispatchOneSentMessage(ThreadQueue) )
{

}



* Now check for normal messages *
if ((ProcessMask & QS_POSTMESSAGE) &&
MsqPeekMessage( ThreadQueue
RemoveMessages
Window
MsgFilterMin
MsgFilterMax
ProcessMask
Msg ))
{
return TRUE
}

* Now look for a quit message *
if (ThreadQueue>QuitPosted)
{
* According to the PSDK WM_QUIT messages are always returned regardless
of the filter specified *
Msg>hwnd NULL
Msg>message WM_QUIT
Msg>wParam ThreadQueue>QuitExitCode
Msg>lParam 0
if (RemoveMessages)
{
ThreadQueue>QuitPosted FALSE
ClearMsgBitsMask(ThreadQueue QS_POSTMESSAGE)
pti>pcti>fsWakeBits & ~QS_ALLPOSTMESSAGE
pti>pcti>fsChangeBits & ~QS_ALLPOSTMESSAGE
}
return TRUE
}

* Check for hardware events *
if ((ProcessMask & QS_MOUSE) &&
co_MsqPeekMouseMove( ThreadQueue
RemoveMessages
Window
MsgFilterMin
MsgFilterMax
Msg ))
{
return TRUE
}

if ((ProcessMask & QS_INPUT) &&
co_MsqPeekHardwareMessage( ThreadQueue
RemoveMessages
Window
MsgFilterMin
MsgFilterMax
ProcessMask
Msg))
{
return TRUE
}

* Check for sent messages again *
while ( co_MsqDispatchOneSentMessage(ThreadQueue) )
{
if (HIWORD(RemoveMsg) && bGMSG) Hit TRUE
}
if (Hit) return FALSE

* Check for paint messages *
if ((ProcessMask & QS_PAINT) &&
pti>cPaintsReady &&
IntGetPaintMessage( Window
MsgFilterMin
MsgFilterMax
pti
Msg
RemoveMessages))
{
return TRUE
}

* This is correct check for the current threads timers waiting to be
posted to this threads message queue If any we loop again
*
if ((ProcessMask & QS_TIMER) &&
PostTimerMessages(Window))
{
continue
}

return FALSE
}
while (TRUE)

return TRUE
}

co_MsqDispatchOneSentMessage 里做SendMessageListHead 中取出SendMessage里消息 SendMessage消息处理完跳出循环MsqPeekMessage 搞定PostMessage消息次检查次co_MsqDispatchOneSentMessage没发送SendMessage消息间间隔新SendMessage消息然IntGetPaintMessage PostTimerMessages名字容易理解里出消息优先级提高Paint效率Paint统处理Timer消息事实出优先级低Paint样timer中绘制函数次处理timer前够保证Paint消息已处理出timer确准前面太东西做
需解消息结构Post消息挂队列中
typedef struct _USER_MESSAGE
{
LIST_ENTRY ListEntry
MSG Msg
DWORD QS_Flags
} USER_MESSAGE *PUSER_MESSAGE
Send消息里麻烦
typedef struct _USER_SENT_MESSAGE
{
LIST_ENTRY ListEntry 接受方队列
MSG Msg
DWORD QS_Flags Original QS bits used to create this message
PKEVENT CompletionEvent 做线程唤醒操作
LRESULT* Result
LRESULT lResult
struct _USER_MESSAGE_QUEUE* SenderQueue
struct _USER_MESSAGE_QUEUE* CallBackSenderQueue
SENDASYNCPROC CompletionCallback
ULONG_PTR CompletionCallbackContext
* entry in the dispatching list of the sender's message queue *
LIST_ENTRY DispatchingListEntry 发送方DispatchingMessageList
INT HookMessage
BOOL HasPackedLParam
} USER_SENT_MESSAGE *PUSER_SENT_MESSAGE
家伙真正挂发送队列中数结构MSG中数成员里前提消息2队列中存边发送方DispatchingMessageList表示消息正分发边接受方SentMessagesListHead表示消息发送等处理
co_MsqDispatchOneSentMessage究竟
BOOLEAN FASTCALL
co_MsqDispatchOneSentMessage(PUSER_MESSAGE_QUEUE MessageQueue)
{
PUSER_SENT_MESSAGE SaveMsg Message
PLIST_ENTRY Entry
LRESULT Result
PTHREADINFO pti

if (IsListEmpty(&MessageQueue>SentMessagesListHead))
{
return(FALSE)
}

* remove it from the list of pending messages *
Entry RemoveHeadList(&MessageQueue>SentMessagesListHead)
Message CONTAINING_RECORD(Entry USER_SENT_MESSAGE ListEntry)

pti MessageQueue>Thread>TcbWin32Thread

SaveMsg pti>pusmCurrent
pti>pusmCurrent Message

Processing a message sent to it from another thread
if ( ( Message>SenderQueue && MessageQueue Message>SenderQueue) ||
( Message>CallBackSenderQueue && MessageQueue Message>CallBackSenderQueue ))
{ most likely but to be sure
pti>pcti>CTI_flags | CTI_INSENDMESSAGE Let the user know
}

* insert it to the list of messages that are currently dispatched by this
message queue *
InsertTailList(&MessageQueue>LocalDispatchingMessagesHead
&Message>ListEntry)

ClearMsgBitsMask(MessageQueue Message>QS_Flags)

if (Message>HookMessage MSQ_ISHOOK)
{ Direct Hook Call processor
Result co_CallHook( Message>Msgmessage HookId
(INT)(INT_PTR)Message>Msghwnd Code
Message>MsgwParam
Message>MsglParam)
}
else if (Message>HookMessage MSQ_ISEVENT)
{ Direct Event Call processor
Result co_EVENT_CallEvents( Message>Msgmessage
Message>Msghwnd
Message>MsgwParam
Message>MsglParam)
}
else
{ * Call the window procedure *
Result co_IntSendMessage( Message>Msghwnd
Message>Msgmessage
Message>MsgwParam
Message>MsglParam)
}

* remove the message from the local dispatching list because it doesn't need
to be cleaned up on thread termination anymore *
RemoveEntryList(&Message>ListEntry)

* remove the message from the dispatching list if needed so lock the sender's message queue *
if ((Message>HookMessage & MSQ_SENTNOWAIT))
{
if (Message>DispatchingListEntryFlink NULL)
{
* only remove it from the dispatching list if not already removed by a timeout *
RemoveEntryList(&Message>DispatchingListEntry)
}
}
* still keep the sender's message queue locked so the sender can't exit the
MsqSendMessage() function (if timed out) *

if (Message>QS_Flags & QS_SMRESULT)
{
Result Message>lResult
}

* Let the sender know the result *
if (Message>Result NULL)
{
*Message>Result Result
}

if (Message>HasPackedLParam TRUE)
{
if (Message>MsglParam)
ExFreePool((PVOID)Message>MsglParam)
}

* Notify the sender *
if (Message>CompletionEvent NULL)
{
KeSetEvent(Message>CompletionEvent IO_NO_INCREMENT FALSE)
}

* Call the callback if the message was sent with SendMessageCallback *
if (Message>CompletionCallback NULL)
{
co_IntCallSentMessageCallback(Message>CompletionCallback
Message>Msghwnd
Message>Msgmessage
Message>CompletionCallbackContext
Result)
}

* Only if it is not a no wait message *
if ((Message>HookMessage & MSQ_SENTNOWAIT))
{
IntDereferenceMessageQueue(Message>SenderQueue)
IntDereferenceMessageQueue(MessageQueue)
}

* free the message *
ExFreePoolWithTag(Message TAG_USRMSG)

* do not hangup on the user if this is reentering *
if (SaveMsg) pti>pcti>CTI_flags & ~CTI_INSENDMESSAGE
pti>pusmCurrent SaveMsg

return(TRUE)
}

首先SentMessagesListHead消息移动LocalDispatchingMessagesHead略掉细节标志位hook部分co_IntSendMessage消息发送出然结果然消息接收方LocalDispatchingMessagesHead删掉果发送方等消息发送方DispatchingMessagesHead中删掉条消息(消息时间限制已早DispatchingMessagesHead删掉)然返回结果保存起然消息附件资源需释放里消息里赘述关心然通Message>CompletionEvent通知发送方该醒果消息回调函数里没直接调回调函数通消息机制发送消息(Post队列中)确容易理解MSDN相关意思时候真MS文档什全源代码源代码需详细文档?文档真彻底说清楚
转远问题迭代co_IntSendMessage co_IntSendMessage 实co_IntSendMessageTimeout 特殊调
LRESULT FASTCALL
co_IntSendMessageTimeout( HWND hWnd
UINT Msg
WPARAM wParam
LPARAM lParam
UINT uFlags
UINT uTimeout
ULONG_PTR *uResult )
{
PWND DesktopWindow
HWND *Children
HWND *Child

if (HWND_BROADCAST hWnd)
{
return co_IntSendMessageTimeoutSingle(hWnd Msg wParam lParam uFlags uTimeout uResult)
}

DesktopWindow UserGetWindowObject(IntGetDesktopWindow())
if (NULL DesktopWindow)
{
EngSetLastError(ERROR_INTERNAL_ERROR)
return 0
}

* Send message to the desktop window too *
co_IntSendMessageTimeoutSingle(DesktopWindow>headh Msg wParam lParam uFlags uTimeout uResult)

Children IntWinListChildren(DesktopWindow)
if (NULL Children)
{
return 0
}

for (Child Children NULL *Child Child++)
{
co_IntSendMessageTimeoutSingle(*Child Msg wParam lParam uFlags uTimeout uResult)
}

ExFreePool(Children)

return (LRESULT) TRUE
}

考虑广播情况简单单窗口发送消息co_IntSendMessageTimeoutSingle
static LRESULT FASTCALL
co_IntSendMessageTimeoutSingle( HWND hWnd
UINT Msg
WPARAM wParam
LPARAM lParam
UINT uFlags
UINT uTimeout
ULONG_PTR *uResult )
{
NTSTATUS Status
PWND Window NULL
PMSGMEMORY MsgMemoryEntry
INT lParamBufferSize
LPARAM lParamPacked
PTHREADINFO Win32Thread
ULONG_PTR Result 0
DECLARE_RETURN(LRESULT)
USER_REFERENCE_ENTRY Ref

if ((Window UserGetWindowObject(hWnd)))
{
RETURN( FALSE)
}

UserRefObjectCo(Window &Ref)

Win32Thread PsGetCurrentThreadWin32Thread()

IntCallWndProc( Window hWnd Msg wParam lParam)

if ( NULL Win32Thread &&
Window>headpti>MessageQueue Win32Thread>MessageQueue)
{
线程消息直接调户窗口回调函数终结束
Result (ULONG_PTR)co_IntCallWindowProc( Window>lpfnWndProc
Window>Unicode
hWnd
Msg
wParam
lParamPacked
lParamBufferSize )
if(uResult)
{
*uResult Result
}

ObDereferenceObject(Win32Thread>pEThread)

IntCallWndProcRet( Window hWnd Msg wParam lParam (LRESULT *)uResult)

if ( NT_SUCCESS(UnpackParam(lParamPacked Msg wParam lParam FALSE)))
{
DPRINT1(Failed to unpack message parameters\n)
RETURN( TRUE)
}

RETURN( TRUE)
}

线程转发消息

do
{
Status co_MsqSendMessage( Window>headpti>MessageQueue
hWnd
Msg
wParam
lParam
uTimeout
(uFlags & SMTO_BLOCK)
MSQ_NORMAL
uResult )
}
while ((STATUS_TIMEOUT Status) &&
(uFlags & SMTO_NOTIMEOUTIFNOTHUNG) &&
MsqIsHung(Window>headpti>MessageQueue))

IntCallWndProcRet( Window hWnd Msg wParam lParam (LRESULT *)uResult)

if (STATUS_TIMEOUT Status)
{
*
MSDN says
Microsoft Windows 2000 If GetLastError returns zero then the function
timed out
XP+ If the function fails or times out the return value is zero
To get extended error information call GetLastError If GetLastError
returns ERROR_TIMEOUT then the function timed out
*
EngSetLastError(ERROR_TIMEOUT)
RETURN( FALSE)
}
else if ( NT_SUCCESS(Status))
{
SetLastNtError(Status)
RETURN( FALSE)
}

RETURN( TRUE)

CLEANUP
if (Window) UserDerefObjectCo(Window)
END_CLEANUP
}

里终结果然里带出问题系统调写函数呢?什时候调?通什方式?样特第次写windwos程序菜鸟遇第问题问题说清楚挺麻烦部分里先留
脑堆栈弹开始
问题系统调写函数呢?什时候调?通什方式?现回答问题回答系统什时候调窗口程函数
调系统代码说调系统服务API等什通中断机制完成通查找系统调表找相应系统函数时利中断机制执行系统代码(然限制)系统时执行户空间代码?点难思考复杂机制做类似工作思考中种调窗口程函数
容易想时执行户代码难没硬件支持完成类似中断机制系统特定方机会执行窗口程函数显然GetMessage执行户窗口程函数方户程序处理消息时系统没办法作等户次调GetMessage类似函数重新获代码控制co_IntPeekMessage中出端倪果消息队列中没消息GetMessage会退出执行权户代码进入等状态果时SendMessage消息线程会唤醒执行代码非Post消息会GetMessage返回户空间
换句话果Sendmessage发线程GetMessage函数部执行果接收方线程阻塞SendMessage会返回没执行GetMessage
思考问题Sendmessage线程线程没执行GetMessage执行代码线程起显然挂起等?接受线程发送消息显然处理处理前讨种情况确意思windwos角度需实现种强壮消息机制什程呢?清楚点实需种机制等方线程处理完毕前处理发消息哈哈WaitForMultipleObjects等2event等处理完毕消息等sendmessage新消息醒时判断什清醒果面线程力继续循环等sendmessage程
NTSTATUS FASTCALL
co_MsqSendMessage(PUSER_MESSAGE_QUEUE MessageQueue
HWND Wnd UINT Msg WPARAM wParam LPARAM lParam
UINT uTimeout BOOL Block INT HookMessage
ULONG_PTR *uResult)
{
PTHREADINFO pti
PUSER_SENT_MESSAGE Message
KEVENT CompletionEvent
NTSTATUS WaitStatus
PUSER_MESSAGE_QUEUE ThreadQueue
LARGE_INTEGER Timeout
PLIST_ENTRY Entry
LRESULT Result 0 Result could be trashed

if((Message ExAllocatePoolWithTag(PagedPool sizeof(USER_SENT_MESSAGE) TAG_USRMSG)))
{
DPRINT1(MsqSendMessage() Not enough memory to allocate a message)
return STATUS_INSUFFICIENT_RESOURCES
}

KeInitializeEvent(&CompletionEvent NotificationEvent FALSE)

pti PsGetCurrentThreadWin32Thread()
ThreadQueue pti>MessageQueue
ASSERT(ThreadQueue MessageQueue)

TimeoutQuadPart (LONGLONG) uTimeout * (LONGLONG) 10000

* FIXME increase reference counter of sender's message queue here *

Message>Msghwnd Wnd
Message>Msgmessage Msg
Message>MsgwParam wParam
Message>MsglParam lParam
Message>CompletionEvent &CompletionEvent
Message>Result &Result
Message>lResult 0
Message>QS_Flags 0
Message>SenderQueue ThreadQueue
Message>CallBackSenderQueue NULL
IntReferenceMessageQueue(ThreadQueue)
Message>CompletionCallback NULL
Message>CompletionCallbackContext 0
Message>HookMessage HookMessage
Message>HasPackedLParam FALSE

IntReferenceMessageQueue(MessageQueue)

* add it to the list of pending messages *
InsertTailList(&ThreadQueue>DispatchingMessagesHead &Message>DispatchingListEntry)

* queue it in the destination's message queue *
InsertTailList(&MessageQueue>SentMessagesListHead &Message>ListEntry)

Message>QS_Flags QS_SENDMESSAGE
MsqWakeQueue(MessageQueue QS_SENDMESSAGE TRUE)

* we can't access the Message anymore since it could have already been deleted *

if(Block)
{
绝部分阻塞
}
else
{
PVOID WaitObjects[2]

WaitObjects[0] &CompletionEvent
WaitObjects[1] ThreadQueue>NewMessages
do
{
UserLeaveCo()

WaitStatus KeWaitForMultipleObjects(2 WaitObjects WaitAny UserRequest
UserMode FALSE (uTimeout &Timeout NULL) NULL)

UserEnterCo()

if(WaitStatus STATUS_TIMEOUT)
{

}
while (co_MsqDispatchOneSentMessage(ThreadQueue))

}
while (NT_SUCCESS(WaitStatus) && STATUS_WAIT_0 WaitStatus)
}

if(WaitStatus STATUS_TIMEOUT)
*uResult (STATUS_WAIT_0 WaitStatus Result 1)

return WaitStatus
}

GetMessage返回般跑2函数
TranslateMessage(&msg) 
DispatchMessage(&msg)
里讨TranslateMessage辅助硬件消息相关
DispatchMessage事情做调相窗口程部分部分系统调代码目前没什兴趣
类似模态窗口产生模态窗口窗口会阻塞消息阻塞消息线程然发SendMessage什呢?间会联系?



Win32k(2) 报文驱动通信机制
.应层api
int APIENTRY _tWinMain(HINSTANCE hInstance
                     HINSTANCE hPrevInstance
                     LPTSTR    lpCmdLine
intnCmdShow)
{
    WNDCLASSEXwcex
    wcexlpfnWndProc  WndProc
    wcexcbClsExtra      0
RegisterClassEx(&wcex)
 
    hWnd CreateWindow(szWindowClass szTitle WS_OVERLAPPEDWINDOWCW_USEDEFAULT 0CW_USEDEFAULT 0 NULL NULL hInstance NULL)
 
    while(GetMessage(&msg NULL 0 0))NtUserGetMessage
    {
NtUserGetMessage目循环获取普通报文
循环中会检查发送报文方sendmessage会NtUserGetMessage部直接调wndproc立响应
果没普通报文(post 硬件报文定时器报文等)睡眠循环等
       if(TranslateAccelerator(msghwnd hAccelTable &msg))
       {
           TranslateMessage(&msg)键盘扫描码变成unicode
           DispatchMessage(&msg)wndproc调
       }
    }
 
然WndProc函数中调SendMessagePostQuitMessage等等函数
 
应层消息结构
struct MSG
{
   HWND hwnd
   UINT message
   WPARAM wParam
   LPARAM lParam
   DWORD time
   POINT pt
}
 
二.创建窗口NtUserCreateWindowEx
控件什算window
创建窗口应window_object返回句柄
Window_object里面包含许字段里面户填充WndProc址消息队列结构

三接收报文NtUserGetMessage
 
根HWNDhWnd全局句柄表中找窗口
 
关注co_IntPeekMessage调w32thread里面拆取消息队列中消息
Win
typedefstruct _tagTHREADINFO           156 elements 0x208 bytes (sizeof)
{
*0x0BC*     struct _tagQ* pq input queue
*0x0E0*     struct _tagSMS* psmsSent send queue (sent)
*0x0E4*     struct _tagSMS* psmsCurrent send queue (current)
*0x0E8*     struct _tagSMS* psmsReceiveList send queue (received)
*0x174*     struct _tagMLISTmlPost post queue
} tagTHREADINFO *PtagTHREADINFO
 
Ros
typedefstruct_USER_MESSAGE_QUEUE
{
* Reference counter only access this variable with interlocked functions *
LONGReferences
* Owner of the message queue *
struct _ETHREAD *Thread
* Queue of messages sent to the queue *
LIST_ENTRYSentMessagesListHead
* Queue of messages posted to the queue *
LIST_ENTRYPostedMessagesListHead
* Queue of sentmessage notifies for the queue *
LIST_ENTRYNotifyMessagesListHead
* Queue for hardware messages for the queue *
LIST_ENTRYHardwareMessagesListHead
* List of timers sorted on expiry time (earliest first) *
LIST_ENTRYTimerListHead
 
* messages that are currently dispatched by other threads *
LIST_ENTRYDispatchingMessagesHead
* messages that are currently dispatched by this message queue required for cleanup *
LIST_ENTRYLocalDispatchingMessagesHead
 
(1)获取send报文:
步方式消息传递
 
发送方消息挂入发送方DispatchingMessagesHead挂入接收方SentMessagesListHead等Message>CompletionEvent
 
接收方SentMessagesListHead提出消息挂入LocalDispatchingMessagesHead调窗口wndproc者消息钩子完成摘Message>CompletionEvent通知发送方
BOOLFASTCALL
co_IntPeekMessage(PUSER_MESSAGEMsg
PWINDOW_OBJECTWindow
UINTMsgFilterMin
UINTMsgFilterMax
UINTRemoveMsg)
{
 

while (co_MsqDispatchOneSentMessage(ThreadQueue))

句循环摘消息发送消息
 
BOOLEAN FASTCALL
co_MsqDispatchOneSentMessage(PUSER_MESSAGE_QUEUE MessageQueue)
{

 
SentMessagesListHead中获取消息
   Entry RemoveHeadList(&MessageQueue>SentMessagesListHead)
   Message CONTAINING_RECORD(Entry USER_SENT_MESSAGE ListEntry)
 
放入LocalDispatchingMessagesHead
InsertTailList(&MessageQueue>LocalDispatchingMessagesHead
&Message>ListEntry)
消息钩子行处理
if (Message>HookMessage MSQ_ISHOOK)
   {
      Result co_HOOK_CallHooks()

   }
elseif (Message>HookMessage MSQ_ISEVENT)
   {
      Result co_EVENT_CallEvents()                                  
   }
else
   {
调应层窗口函数wndproc
        Result co_IntSendMessage()
   }
已送达删
RemoveEntryList(&Message>ListEntry)
 
* remove the message from the dispatching list so lock the sender's message queue *
SenderReturned (Message>DispatchingListEntryFlink NULL)
if(SenderReturned)
   {
DispatchingListEntry中移
RemoveEntryList(&Message>DispatchingListEntry)
   }
* Let the sender know the result *
if (Message>Result NULL)
   {
返回wndproc执行结果
      *Message>Result Result
   }
 
* Notify the sender *
if (Message>CompletionEvent NULL)
   {
通知发送方唤醒
KeSetEvent(Message>CompletionEvent IO_NO_INCREMENT FALSE)
   }
 
方回调函数处理略
* Notify the sender if they specified a callback *
if (SenderReturned&& Message>CompletionCallback NULL)
   {

   }

* free the message *
ExFreePool(Message)
return(TRUE)
}
 
 
里面co_IntSendMessage终调co_IntCallWindowProc
调KeUserModeCallback(USER32_CALLBACK_WINDOWPROC返回r3
处暂略
 
(2)获取报文
 
NtUserGetMessage co_IntPeekMessage    
 
 
 
BOOLFASTCALL
co_IntPeekMessage(PUSER_MESSAGEMsg
PWINDOW_OBJECTWindow
UINTMsgFilterMin
UINTMsgFilterMax
UINTRemoveMsg)
{
 
sent报文处理已分析
while (co_MsqDispatchOneSentMessage(ThreadQueue))
接报文伪代码
 
般post报文
* Now check for normal messages *
Present co_MsqFindMessage(ThreadQueue
if (Present)
{
gotoMessageFound
}
硬件报文
* Check for hardware events *
Present co_MsqFindMessage(ThreadQueue
if (Present)
{
gotoMessageFound
}
次检查sent报文
* Check for sent messages again *
while (co_MsqDispatchOneSentMessage(ThreadQueue))
paint报文
* Check for paint messages *
if (IntGetPaintMessage(Window MsgFilterMin MsgFilterMax pti &Msg>Msg RemoveMessages))
{
Msg>FreeLParam FALSE
gotoMsgExit
}
定时器报文(包括鼠标)
Present MsqGetTimerMessage(ThreadQueue Window MsgFilterMin MsgFilterMax
&Msg>Msg RemoveMessages)
if (Present)
{
Msg>FreeLParam FALSE
gotoMessageFound
}
 
报文窗口程序发送鼠标键盘线程投递
 
 
(3)DispatchMessage应NtUserDispatchMessage简单消息派发出调wndproc者hook
四.发送视窗报文
(1)Post message
Post简单插入链表发送消息根Wnd找应window object然插入post链表时间通知消息
 
 
NtUserPostMessage–UserPostMessage UserPostThreadMessage MsqPostMessage
 
VOIDFASTCALL
MsqPostMessage(PUSER_MESSAGE_QUEUEMessageQueue MSG* Msg BOOLEANFreeLParam
DWORDMessageBits)
{
PUSER_MESSAGEMessage
 
if((Message MsqCreateMessage(Msg FreeLParam)))
   {
return
   }
InsertTailList(&MessageQueue>PostedMessagesListHead
&Message>ListEntry)
MessageQueue>QueueBits | MessageBits
MessageQueue>ChangedBits | MessageBits
if (MessageQueue>WakeMask&MessageBits)
KeSetEvent(MessageQueue>NewMessages IO_NO_INCREMENT FALSE)
}
(2)send message
果身线程发送消息send直接回调线程wndproc
否话调co_MsqSendMessage
 
co_MsqSendMessage(PUSER_MESSAGE_QUEUE MessageQueue接收方队列
                  HWND Wnd UINT Msg WPARAM wParam LPARAM lParam
                  UINT uTimeout BOOL Block INT HookMessage
                  ULONG_PTR *uResult)
{
……
if((Message ExAllocatePoolWithTag(PagedPool sizeof(USER_SENT_MESSAGE) TAG_USRMSG)))
……
 
KeInitializeEvent(&CompletionEvent NotificationEvent FALSE)
 
pti PsGetCurrentThreadWin32Thread()
ThreadQueue pti>MessageQueue 发送方队列
 
TimeoutQuadPart (LONGLONG) uTimeout * (LONGLONG) 10000
 
……初始化Message结构
 
* 挂入两队列进程DispatchingListEntry方进程SentMessagesListHead*
InsertTailList(&ThreadQueue>DispatchingMessagesHead &Message>DispatchingListEntry)
InsertTailList(&MessageQueue>SentMessagesListHead &Message>ListEntry)
 
……果方正等报文唤醒
if (MessageQueue>WakeMask&QS_SENDMESSAGE)
KeSetEvent(MessageQueue>NewMessages IO_NO_INCREMENT FALSE)
 

if(Block)阻塞方式单纯等消息完成事件CompletionEvent
   {
……
* 等报文处理*
WaitStatus KeWaitForSingleObject(&CompletionEvent UserRequest UserMode
                                         FALSE (uTimeout &Timeout NULL))
 
……
超时话
if(WaitStatus STATUS_TIMEOUT)
      {
* 方sent链表里面消消息*
         Entry MessageQueue>SentMessagesListHeadFlink
while (Entry &MessageQueue>SentMessagesListHead)
         {
if ((PUSER_SENT_MESSAGE) CONTAINING_RECORD(Entry USER_SENT_MESSAGE ListEntry)
                  Message)
            {
               Message>CompletionEvent NULL
               Message>Result NULL
break
            }
            Entry Entry>Flink
         }
 
*Dispatching消消息 *
         Entry ThreadQueue>DispatchingMessagesHeadFlink
while (Entry &ThreadQueue>DispatchingMessagesHead)
         {
if ((PUSER_SENT_MESSAGE) CONTAINING_RECORD(Entry USER_SENT_MESSAGE DispatchingListEntry)
                  Message)
            {
               Message>CompletionEvent NULL
               Message>Result NULL
RemoveEntryList(&Message>DispatchingListEntry)
               Message>DispatchingListEntryFlink NULL
break
            }
            Entry Entry>Flink
         }
      }
里捎带脚吧发消息处理
while (co_MsqDispatchOneSentMessage(ThreadQueue))
   }
else非阻塞方式等消息完成事件CompletionEvent方报文贴时短暂唤醒处理
   {
 PVOID WaitObjects[2]
 
WaitObjects[0] &CompletionEvent
WaitObjects[1] ThreadQueue>NewMessages
do
      {
IdlePing()
 
UserLeaveCo()
 
WaitStatus KeWaitForMultipleObjects(2 WaitObjects WaitAny UserRequest
UserMode FALSE (uTimeout &Timeout NULL) NULL)
 
……
超时话面样移两链表中消息处理sent链表方发送消息
      }
while (NT_SUCCESS(WaitStatus) && STATUS_WAIT_0 WaitStatus) CompletionEvent满足等
   }
 
if(WaitStatus STATUS_TIMEOUT)
      *uResult (STATUS_WAIT_0 WaitStatus Result 1)
 
returnWaitStatus
}

文档香网(httpswwwxiangdangnet)户传

《香当网》用户分享的内容,不代表《香当网》观点或立场,请自行判断内容的真实性和可靠性!
该内容是文档的文本内容,更好的格式请下载文档

下载文档,方便阅读与编辑

文档的实际排版效果,会与网站的显示效果略有不同!!

需要 10 香币 [ 分享文档获得香币 ]

该文档为用户出售和定价!

购买文档

相关文档

$windows内核情景分析学习笔记

windows内核情景分析学习笔记6分类: windows MFC2010-10-19 11:37226人阅读评论(0)收藏举报1、用于数据存储的内存区间分类①全局数据所占空间。由编译器在编译链接时就静态分配好的,与整个进程共存亡。其分配和释放都是不可见、不可为的②局部数据所占的空间。调用函数时自动从堆栈上动态分配的,其寿命取决于函数的作用域。其分配和释放是隐含的。③通过malloc一

奋斗不止500年 3年前 上传379   0

2021年reactos仿windows系统内核源代码研究

引导序号引导过程引导执行代码位数目标文件名称1.         主引导代码(Master Boot Record (MBR)code),主要寻找活动分区,然后读入引导扇区代码16位执行代码reactos/boot/freeldr/bootsect/dosmbr.asm2.         引导扇区代码,主要寻找根据的引导程序,这里主要寻找freeldr.sys。16位执行代

奋斗不止500年 3个月前 上传201   0

老党员发挥余热 提升偏坡文化内核

“老主席,区委组织部到你家来采访了,请问你现在在家不?”,“我还在下院村参加老年协会活动,今天恐怕要忙到下午才能回来,你请他们明天来吧。”

n***3 3年前 上传506   0

有感于青啤集团总裁《把社会责任感纳入企业内核》

有感于青啤集团总裁《把社会责任感纳入企业内核》提高企业社会责任感          —有感于青啤集团总裁《把社会责任感纳入企业内核》    “一个没有责任感的企业是不可能持续成长的,也不可能成就一个国际化的大企业”,这是青啤集团总裁在《把社会责任感纳入企业内核》中的一句话,读完此篇,感慨颇深,青啤集团一个百年的大企业之所以在全球具有影响力,不仅在于它实力的强大,精湛的技术,过硬的产品

d***2 10年前 上传364   0

常用成语解析

常用成语汇编   A 黯然销魂:形容非常悲伤或愁苦。 安步当车:慢慢的步行,就当是坐车。 按部就班:按照一定的步骤、顺序进行。也指按老规矩办事,缺乏创新精神。 按图索骥:比喻按照线索寻找,也比喻办事机械死板。 嗷嗷待哺:常用以形容饥民渴求得食而急待解救的悲惨情景。 哀而不伤:多形容诗歌、音乐等具有中和之美。也比喻处事适中,没有过与不及之处。 哀丝豪竹:形容管弦乐声的悲壮动人。

林***o 10年前 上传8313   0

解析项目管理

解析项目管理文章来源:中国计算机用户 作者:北京中科项目管理研究所所长 席相霖提起项目管理,人们好像都能侃几句,可是要再多说几句,却又说不出个所以然。不过,尽管这样,人们对它的前景倒还是很看好。有人说它比MBA更有前途,也有人对项目管理的资质认证很感兴趣。本栏目的宗旨就是介绍项目管理的方方面面,所以今天将给大家介绍一下项目管理的发展过程和知识体系等,并且将在以后陆续介绍项目管理

无***档 11年前 上传493   0

解析LG精神

解析LG精神   韩国LG公司的企业徽标是一张象形的人脸。许多人说,它上面那一只张着一只闭着的眼代表乐观看世界;LG的人说,它象征着韩国人的生机活力。而对于在LG公司工作了36年的现任副会长卢庸岳先生,他说这是一张未来之脸,它包含着LG公司走出国门、走入世界、走向未来的一种精神面貌。   这张未来之脸是LG公司拓展海外市场的见证人。卢庸岳先生从1978年起开始负责LG公司所有海外市场的规

a***4 12年前 上传632   0

合同效力解析

论合同的效力   摘要 合同,从根本说体现着民事法律的精髓,体现着当事人通过自己的意思表示和行为,创建法律上的权利义务的自主权,从根本上说,合同制度是对当事人意志的尊重和对市场制度下分散决策权的确认,意味着在一个国家内,在市场制度下,人们合同行为的一致性,自然,也是民法制度的一种完善,从另一层面讲,更是社会生产关系的一种进步,而合同效力又是合同法中的核心。 关键词:合同效力、附条件或附期

王***芳 11年前 上传11310   0

易经重要术语解析

易经重要术语解析太极宇宙原始而混沌的状态太极,是原始,也是无穷,是宇宙原始而混沌的状态。大家知道,原始的数是一,《说文解字》中说:“惟初太极,道立于一,造分天地,化成万物。”可见太极既为初为一,可化成万物,又可至于无穷。太极原是天地、乾坤、刚柔、阴阳、理气等一切相对事物的一个混合体,可以不断二分。但无论经过多少次的二分,其分子永远是太极,也就是一。所以《朱子语类》中朱熹回答陈

d***9 10年前 上传670   0

职代会报告解析

职代会报告解析 公司“二届三次”职代会报告不仅对公司2011年的工作进行了科学、客观、系统的总结分析,而且对公司2012年的工作详细、科学的规划,是一篇全局性、战略性、指导性很强的报告,对于公司上下坚定发展信心,理清发展思路,转变发展方式,具有重要的意义和作用。我本人通过先后10余次对二届二次职代会报告的学习,对公司目前的发展形势及未来的发展规划有了新的认识,今年的职代会报告与往年最大的不同就

笑***2 10年前 上传9306   0

精品解析:2023年 中考道德与法治真题(解析版)

1. 中学生要把握机遇,从点滴做起,为实现远大理想( )A. 不懈努力 B. 听天由命 C. 拒绝帮助 D. 依赖父母【答案】A【解析】【详解】本题考查对实现梦想的认识和理解。

蓝郎梦 10个月前 上传580   1

精品解析:2024中考道德与法治真题(解析版)

1. 2020年5月7日电,________已通过生态环境部组织的国家生态省建设试点验收,建成中国首个生态省。( )A. 浙江省 B. 江苏省 C. 山东省 D. 福建省【答案】A【解析】【详解】本题为时政题,解析略。

蓝郎梦 10个月前 上传435   1

促销深度解析

促销深度解析中国营销传播网, 2004-12-10, 作者: 毛浓月, 访问人数: 341  不少企业只要销量一下滑,首先想到的对策就是举办促销活动。因为促销可以迅速见效应,可以造成一派繁荣的市场景象。   从企业角度来分析,造成不少企业热衷于商业品促销的根本原因是:企业的经理们期待立竿见影的市场成效。这是在短期内解决销量问题最有效的法宝,经理们都这样认为,有基于董事会指

中***8 11年前 上传512   0

2.2气温 同步练习(含解析)

一、单选题1.2020年8月份杭州市某区气象台多次发布高温橙色预警信号:受副热带高压影响,预计我区部分地区的最高气温可达38C或以上,望各有关方面注意做好防暑降温工作。而该区的西天目山、清凉峰等都是首选的避暑胜地,造成此差异的主要原因是( ) A. 地貌的不同 B. 海陆位置的影响 C. 纬度位置的影响 D. 人类活动的影响2.如图为某四个地点气温年变化曲线图。图示四地气温变化( )

文***7 1年前 上传521   0

目标成本规划解析

目标成本规划解析 本文深入分析了目标成本规划法所体现的战略性成本管理思想,认为目标成本规划的中心问题是如何设计和传递各种成本压力。本文的分析还表明,虽然邯钢经验与目标成本规划在某些具体做法上具有很大的相似性,但两者之间是具有本质性区别的。   【关键词】目标成本规划邯钢经验   随着全球性竞争的日益加剧以及商品市场因消费者的个性化需求而进一步被细化,企业要

d***d 8年前 上传5942   0

2017年实习报告题目解析

实习报告题目解析  一.从实习的工作内容出发。比如,某教育专业的学生到某学校实习,题目可以“化学教师实习报告”“英语教师实习报告”等等;某学生做咨询的实习,题目可以是“投资咨询实习报告”“法律咨询实习报告”等等。这类题目越详细越好,甚至可以是做的很小的一方面。  二.从实习的地点出发。有很多题目都是这样的:xx公司实习报告,xx中学实习报告等。  三.实习的内容加地点。这样可以更加详

t***t 7年前 上传495   0

ADSS安装手册解析

全介质自承式〔ADSS〕光缆安装培训手册四川汇源光通信四川汇源光通信目 录安装培训手册第一局部 光缆根底学问 1其次局部 ADSS 光缆安装 5第一章 根底学问 5第 1 节 光缆挂点的选择 5第 2 节 ADSS 光缆安装的根本技术要求……………………… 8其次章 ADSS 光

7***2 1年前 上传259   0

ITV故障处理解析

?ITV故障处理解析 1. 1. 网络侧故障:一  1.1303(本地网络未连接,请检查网线或ADSL MODEM状态)                         2.1305(1、机顶盒第一层设置的网络接入帐号或者密码错误;2、网络接入帐号7001平台绑定端口不对、用户数3、网络接入帐号限制用户数或者帐号状态不对、4、接入层的用户端口数据问题、5、机顶盒或者moderm问题、6、上

啊***i 9年前 上传8789   0

中考真题解析 物理

中考真题解析 物理

顾***1 4年前 上传1195   0

HRBP的角色定位解析

HR BP的角色定位解析朱帅标题起的有点吓人,谈不上解析,更多是这10年来HR转型过程中的一些体会,不知从标题的抓眼球功能上能帮我多挣点百度文库的经验值。选育用留,六大模块,谈到HR自然而然会有这个直观感受,功能性的切分、职能部门的定位,HR对业务部门来说,一直很有距离感,直到HRBP的出现。对比HRBP和各模块的区分,可能很多企业已有尝试,有侧重的,也有并线发展的。举个通俗

m***0 12年前 上传786   0

解析知识管理的权力结构

解析知識管理的權力結構-與紀登斯〔A. Giddens〕和傅柯〔M. Foucault〕的對話-范家豪國立台南大學教育經營與管理研究所博士生摘要  本文旨在以社會學理論的觀點,進行「知識管理」〔knowledge management〕權力結構的解析。首先,引藉紀登斯〔Anthony Giddens〕的「結構化理論」,論辯知識管理具有一種資源與規則組成的「結構」型式。繼而,經

郭***林 5个月前 上传135   0

解析新药研发WBS

解析新药研发WBS在讨论WBS(工作分解结构,WORKBREAKDOWNSTRUATURE)之前,我们先来看看新药研发的特点。新药研发一般具有以下特点: 首先是周期长。一类新药研究从发现苗头到最后批准投产上市需要经过漫长的过程,有关资料表明国外新药研发一般需要10-15年时间,我国也要6-10年的时间。 其次是高投入、高风险。在美国开发一个新药往往要投入数亿美元,国内以往以仿制研发为主,所需

O***1 10年前 上传575   0

解析几何

Mxyo·第18题1. 已知⊙和点.(1)过点向⊙引切线,求直线的方程;(Ⅱ)求以点为圆心,且被直线截得的弦长为 4的⊙的方程;(Ⅲ)设为(Ⅱ)中⊙上任一点,过点向⊙引切线,切点为Q. 试探究:平面内是否存在一定点,使得为定值?若存在,请举出一例,并指出相应的定值;若不存在,请说明理由.解:(Ⅰ)设切线方程为 ,易得,解得……3分 ∴切线方程为

p***1 11年前 上传604   0

《解析几何》教案

第一章 向量与坐标本章教学目的:通过本章学习,使学生掌握向量及其运算的概念,熟练掌握线性运算和非线性运算的基本性质、运算规律和分量表示,会利用向量及其运算建立空间坐标系和解决某些几何问题,为以下各章利用代数方法研究空间图形的性质打下基础.本章教学重点: (1)向量的基本概念和向量间关系的各种刻划。(2)向量的线性运算、积运算的定义、运算规律及分量表示.本章教学难点: (1)向量及其运算与空间坐标系的联系;(2)向量的数量积与向量积的区别与联系;(3)向量及其运算在平面、立体几何中的应用.本章教学内容: §1.1 向量的基本概念 一、定义:既有大小又有方向的量称为向量,如力、速度、位移等.二、表示:在几何上,用带箭头的线段表示向量,箭头表示向量的方向,线段长度代表向量的大小;向量的大小又叫向量的模(长度).始点为A,终点为B的向量,记作 ,其模记做 .注:为方便起见,今后除少数情形用向量的始、终点字母标记向量外,我们一般用小写黑体字母a、b、c……标记向量,而用希腊字母λ、μ、ν……标记数量.三、两种特殊向量:1、零向量:模等于0的向量为零向量,简称零向量,以0记之.注:零向量是唯一方向不定的向量.2、单位向量:模等于1的向量称为单位向量.特别地,与非0向量 同向的单位向量称为 的单位向量,记作 .四、向量间的几种特殊关系:1、平行(共线):向量a平行于向量b,意即a所在直线平行于b所在直线,记作a∥b,规定:零向量平行于任何向量.

王***琴 5年前 上传1363   0

精品解析:2023(农垦 森工)中考道德与法治真题(解析版)

1. 2020年5月7日电,________已通过生态环境部组织的国家生态省建设试点验收,建成中国首个生态省。( )A. 浙江省 B. 江苏省 C. 山东省 D. 福建省【答案】A

蓝郎梦 10个月前 上传244   1