返回列表 回复 发帖

[转帖]驱动程序和应用程序之间通信(For Win2000 or later v)

作者 Fang

关键字 驱动 应用 通信
原作者姓名 Fang
文章原始出处 根据网上一些资料整理。

正文
Q:
请问有什么方法实现驱动程序主动和应用程序进行实时通讯,而不用应用程序采用定时查询的方法?
比如驱动有一事件发生需要立即通知应用程序,或驱动程序需要向应用程序读取一些内容.

A:
有一个很容易的方式,在驱动程序和应用程序之间用一个事件。
在应用程序CreateFile的时候,驱动程序IoCreateSynchronizationEvent一个有名的事件,然后应用程序CreateEvent/OpenEvent此有名事件即可。
注意点:
1,不要在驱动初始化的时候创建事件,此时大多不能成功创建;
2,让驱动先创建,那么此后应用程序打开时,只能读(Waitxxxx),不能写(SetEvent/ResetEvent)。反之,如果应用程序先创建,则应用程序和驱动程序都有读写权限;
3,用名字比较理想,注意驱动中名字在\BaseNamedObjects\下,例如应用程序用“xxxEvent”,那么驱动中就是“\BaseNamedObjects\xxxEvent”;
4,用HANDLE的方式也可以,但是在WIN98下是否可行,未知。
5,此后,驱动对读请求应立即返回,否则就返回失败。不然将失去用事件通知的意义(不再等待读完成,而是有需要(通知事件)时才会读);
6,应用程序发现有事件,应该在一个循环中读取,直到读取失败,表明没有数据可读;否则会漏掉后续数据,而没有及时读取;

Sample Code:
  1. // Describe the share memory.
  2. typedef struct _PKT_BUFFER
  3. {
  4. PMDL BufferMdl;
  5. PVOID UserBaseAddress;
  6. PVOID KernelBaseAddress;
  7. }PKT_BUFFER, *PPKT_BUFFER;
  8. typedef struct _SHARE_EVENT_CONTEXT
  9. {
  10. WCHAR EventName[128]; // Event name, the only connection btw ring0/ring3
  11. HANDLE Win32EventHandle; // Ring3 copy of the event handle
  12. HANDLE DriverEventHandle; // Ring0 copy of the event handle
  13. PVOID DriverEventObject; // The event object
  14. }SHARE_EVENT_CONTEXT, *PSHARE_EVENT_CONTEXT;
  15. BOOLEAN CreateShareMemory(PPKT_BUFFER PktBuffer, ULONG Size)
  16. {
  17. PktBuffer->KernelBaseAddress = ExAllocatePoolWithTag(NonPagedPool,
  18. Size,
  19. 'MpaM');
  20. if(!PktBuffer->KernelBaseAddress)
  21. return FALSE;
  22. //
  23. // Allocate and initalize an MDL that describes the buffer
  24. //
  25. PktBuffer->BufferMdl = IoAllocateMdl(PktBuffer->KernelBaseAddress,
  26. Size,
  27. FALSE,
  28. FALSE,
  29. NULL);
  30. if(!PktBuffer->BufferMdl)
  31. {
  32. ExFreePool(PktBuffer->KernelBaseAddress);
  33. PktBuffer->KernelBaseAddress =NULL;
  34. return FALSE;
  35. }
  36. MmBuildMdlForNonPagedPool(PktBuffer->BufferMdl);
  37. DEBUGP(DL_INFO, ("CreateShareMemory: KernelBaseAddress = 0x%p\n", PktBuffer->KernelBaseAddress));
  38. return TRUE;
  39. }
  40. VOID DestroyShareMemory(PPKT_BUFFER PktBuffer)
  41. {
  42. if(PktBuffer->BufferMdl)
  43. {
  44. IoFreeMdl(PktBuffer->BufferMdl);
  45. PktBuffer->BufferMdl = NULL;
  46. }
  47. if(PktBuffer->KernelBaseAddress)
  48. {
  49. ExFreePool(PktBuffer->KernelBaseAddress);
  50. PktBuffer->KernelBaseAddress = NULL;
  51. }
  52. }
  53. //This function works in user dispatch code.
  54. BOOLEAN MapSharedMemory(PPKT_BUFFER PktBuffer)
  55. {
  56. if(!PktBuffer->BufferMdl)
  57. return FALSE;
  58. //
  59. // The preferred V5 way to map the buffer into user space
  60. //
  61. PktBuffer->UserBaseAddress =
  62. MmMapLockedPagesSpecifyCache(PktBuffer->BufferMdl, // MDL
  63. UserMode, // Mode
  64. MmCached, // Caching
  65. NULL, // Address
  66. FALSE, // Bugcheck?
  67. NormalPagePriority); // Priority
  68. if(!PktBuffer->UserBaseAddress)
  69. return FALSE;
  70. DEBUGP(DL_INFO, ("MapSharedMemory SUCCESS, UserBaseAddress %p\n", PktBuffer->UserBaseAddress));
  71. return TRUE;
  72. }
  73. VOID UnmapSharedMemory(PPKT_BUFFER PktBuffer)
  74. {
  75. if(PktBuffer->UserBaseAddress)
  76. {
  77. MmUnmapLockedPages(PktBuffer->UserBaseAddress, PktBuffer->BufferMdl);
  78. PktBuffer->UserBaseAddress = NULL;
  79. }
  80. }
  81. BOOLEAN CreateShareEvent(PSHARE_EVENT_CONTEXT ShareEvent)
  82. {
  83. UNICODE_STRING UnicodeName;
  84. WCHAR UnicodeBuffer[128] = L"\BaseNamedObjects\";
  85. RtlInitUnicodeString(&UnicodeName, UnicodeBuffer);
  86. UnicodeName.MaximumLength = 128;
  87. RtlAppendUnicodeToString(&UnicodeName, ShareEvent->EventName);
  88. ShareEvent->DriverEventObject = IoCreateSynchronizationEvent(&UnicodeName,
  89. &ShareEvent->DriverEventHandle);
  90. if(ShareEvent->DriverEventObject == NULL)
  91. {
  92. ShareEvent->DriverEventHandle = NULL;
  93. DEBUGP(DL_INFO, ("CreateSynchronizationEvent FAILED Name=%ws\n", UnicodeBuffer));
  94. return FALSE;
  95. }
  96. else
  97. {
  98. KeClearEvent(ShareEvent->DriverEventObject);
  99. DEBUGP(DL_INFO, ("CreateSynchronizationEvent SUCCESS Name=%ws DriverEventObject=%p, DriverEventHandle=%u\n",
  100. UnicodeBuffer,
  101. ShareEvent->DriverEventObject,
  102. ShareEvent->DriverEventHandle));
  103. return TRUE;
  104. }
  105. }
  106. VOID DestroyShareEvents(PSHARE_EVENT_CONTEXT ShareEvent)
  107. {
  108. if(ShareEvent->DriverEventHandle)
  109. {
  110. ZwClose(ShareEvent->DriverEventHandle);
  111. ShareEvent->DriverEventObject = NULL;
  112. ShareEvent->DriverEventHandle = NULL;
  113. }
  114. }
复制代码

                     我是一个呼吸着现在的空气而生活在过去的人
               这样的注定孤独,孤独的身处闹市却犹如置身于荒漠
                                     我已习惯了孤独,爱上孤独
                                 他让我看清了自我,还原了自我
                             让我再静静的沉思中得到快乐和满足
                                   再孤独的世界里我一遍又一遍
                                   不厌其烦的改写着自己的过去
                                             延伸到现在与未来
                                       然而那只是泡沫般的美梦
                                 产生的时刻又伴随着破灭的到来
                         在灰飞烟灭的瞬间我看到的是过程的美丽
                                      而不是结果的悲哀。。。
返回列表