pzm
pzm
驱动牛犊
驱动牛犊
  • 注册日期2001-12-29
  • 最后登录2016-01-09
  • 粉丝0
  • 关注0
  • 积分0分
  • 威望0点
  • 贡献值0点
  • 好评度0点
  • 原创分0分
  • 专家分0分
阅读:1546回复:4

急急, 应用程序非正常退出, 驱动如何关闭句柄, 高分伺候

楼主#
更多 发布于:2002-06-03 15:43
做一个socket驱动, socket创建一个socket结构(自定义)问题是如果上层的应用程序非正常退出(被杀死), 则该内存将永远保留, 除非重启,

那位高手知道如何避免, 在进程被杀死时有什么事件通知驱动?



[编辑 -  6/3/02 by  pzm]

最新喜欢:

sunmaculasunmac...
Dragon2008
驱动中牛
驱动中牛
  • 注册日期2002-04-01
  • 最后登录2006-03-13
  • 粉丝0
  • 关注0
  • 积分31分
  • 威望5点
  • 贡献值0点
  • 好评度1点
  • 原创分0分
  • 专家分0分
沙发#
发布于:2002-06-03 16:31
这个问题我也遇到过,不好办。
谁会,告之。我也加分!
我姓龙,我属龙,我叫龙。。。
kavas
驱动牛犊
驱动牛犊
  • 注册日期2001-12-28
  • 最后登录2004-03-17
  • 粉丝0
  • 关注0
  • 积分0分
  • 威望0点
  • 贡献值0点
  • 好评度0点
  • 原创分0分
  • 专家分0分
板凳#
发布于:2002-06-03 22:21
关注!
驱动,驱动,一驱就动。 我怎么就是驱不动它呢? 窝火!!
bocli
驱动牛犊
驱动牛犊
  • 注册日期2001-09-11
  • 最后登录2005-02-03
  • 粉丝0
  • 关注0
  • 积分0分
  • 威望0点
  • 贡献值0点
  • 好评度0点
  • 原创分0分
  • 专家分0分
地板#
发布于:2002-06-04 01:11
Usually it\'s the application\'s responsibility to clean up the memory for drivers.

I don\'t know if following info can help you.



HOWTO: Terminate an Application \"Cleanly\" in Win32
Last reviewed: January 7, 1998
Article ID: Q178893  
The information in this article applies to:
Microsoft Win32 Application Programming Interface (API) included with: - Microsoft Windows NT version 4.0 - Microsoft Windows 95


SUMMARY
In a perfect world, your process could ask another process, through some form of inter-process communication, to shut down. However, if you do not have source-level control of the application that you wish to shut down, then you may not have this option. Although there is no guaranteed \"clean\" way to shut down an application in Win32, there are steps that you can take to ensure that the application uses the best method for cleaning up resources.



MORE INFORMATION


32-Bit Processes (and 16-Bit Processes under Windows 95)
Under Win32, the operating system promises to clean up resources owned by a process when it shuts down. This does not, however, mean that the process itself has had the opportunity to do any final flushes of information to disk, any final communication over a remote connection, nor does it mean that the process\' DLL\'s will have the opportunity to execute their PROCESS_DETACH code. This is why it is generally preferable to avoid terminating an application under Windows 95 and Windows NT.

If you absolutely must shut down a process, follow these steps:


Post a WM_CLOSE to all Top-Level windows owned by the process that you want to shut down. Many Windows applications respond to this message by shutting down. NOTE: A console application\'s response to WM_CLOSE depends on whether or not it has installed a control handler. For additional information, please see the following article in the Microsoft Knowledge Base:


      ARTICLE-ID: Q102429
      TITLE     : HOWTO: Detect Closure of Command Window from a Console
                  App

   Use EnumWindows() to find the handles to your target windows. In your
   callback function, check to see if the windows\' process ID matches
   the process you want to shut down. You can do this by calling
   GetWindowThreadProcessId(). Once you have established a match, use
   PostMessage() or SendMessageTimeout() to post the WM_CLOSE message to
   the window.



Use WaitForSingleObject() to wait for the handle of the process. Make sure you wait with a timeout value, because there are many situations in which the WM_CLOSE will not shut down the application. Remember to make the timeout long enough (either with WaitForSingleObject(), or with SendMessageTimeout()) so that a user can respond to any dialog boxes that were created in response to the WM_CLOSE message.

If the return value is WAIT_OBJECT_0, then the application closed itself down cleanly. If the return value is WAIT_TIMEOUT, then you must use TerminateProcess() to shutdown the application. NOTE: If you are getting a return value from WaitForSingleObject() other then WAIT_OBJECT_0 or WAIT_TIMEOUT, use GetLastError() to determine the cause.

By following these steps, you give the application the best possible chance to shutdown cleanly (aside from IPC or user-intervention).


The 16-Bit Issue (under Windows NT)
The preceding steps work for 16-bit applications under Windows 95, however, Windows NT 16-bit applications work very differently.

Under Windows NT, all 16-bit applications run in a virtual DOS machine (VDM). This VDM runs as a Win32 process (NTVDM) under Windows NT. The NTVDM process has a process ID. You can obtain a handle to the process through OpenProcess(), just like you can with any other Win32 process. Nevertheless, none of the 16-bit applications running in the VDM have a process ID, and therefore you cannot get a Process Handle from OpenProcess(). Each 16-bit application in a VDM has a 16-bit Task Handle and a 32-bit thread of execution. The handle and thread ID can be found through a call to the function VDMEnumTaskWOWEx(). For additional information, please see the following article in the Microsoft Knowledge Base:


   ARTICLE-ID: Q175030
   TITLE     : HOWTO: Enumerate Applications in Win32


Your first, and most straightforward, option when shutting down a 16-bit application under Windows NT is to shut down the entire NTVDM process. You can do this by following the steps outlined above. You only need to know the process ID of the NTVDM process (see the KB article Q175030 cited above to find the process ID of an NTVDM). The downside of this approach is that it closes all 16-bit applications that are running in that VDM. If this is not your goal, then you need to take another approach.
If you wish to shut down a single 16-bit application within a NTVDM process, following are the steps you need to take:


Post a WM_CLOSE to all Top-Level windows that are owned by the process, and that have the same owning thread ID as the 16-bit task you want to shut down. The most effective way to do this is by using EnumWindows(). In your callback function, check to see if the window\'s process ID and thread ID matches the 16-bit task you want to shut down. Remember that the process ID is going to be the process ID of the NTVDM process in which the 16-bit application is running.

Although you have a thread ID, you have no way to wait on the termination of the 16-bit process. As a result, you must wait for an arbitrary length of time (to allow a clean shut down), and then try to shut the application down anyway. If the application has already shut down, then this will do nothing. If it hasn\'t shut down, then it will terminate the application.

Terminate the application using a function called VDMTerminateTaskWOW(), which can be found in the Vdmdbg.dll. It takes the process ID of the VDM and the task number of the 16-bit task.

This approach allows you to shut down a single 16-bit application within a VDM under Windows NT. However, 16-bit Windows is not very good at cleaning up resources of a terminated task, and neither is the WOWExec running in the VDM. If you are looking for the cleanest possible approach to terminating a 16-bit application under Windows NT, you should consider terminating the entire VDM process. NOTE: If you are starting a 16-bit application that you may terminate later, then use the CREATE_SEPARATE_WOW_VDM with CreateProcess().


Sample Code
The sample code implements the techniques described above for 16-bit and 32- bit applications using the following two functions: TerminateApp() and Terminate16App(). TerminateApp() takes a 32-bit process ID and a timeout (in miliseconds). Terminate16App(). Both functions use explicit linking to DLL functions so that they will be binary compatible across Windows NT and Windows 95.


   //******************
   //Header
   //******************

   #include <windows.h>

   #define TA_FAILED 0
   #define TA_SUCCESS_CLEAN 1
   #define TA_SUCCESS_KILL 2
   #define TA_SUCCESS_16 3

   DWORD WINAPI TerminateApp( DWORD dwPID, DWORD dwTimeout ) ;
   DWORD WINAPI Terminate16App( DWORD dwPID, DWORD dwThread,
                        WORD w16Task, DWORD dwTimeout );

   //******************
   //Source
   //******************

   #include \"TermApp.h\"
   #include <vdmdbg.h>

   typedef struct
   {
      DWORD   dwID ;
      DWORD   dwThread ;
   } TERMINFO ;

   // Declare Callback Enum Functions.
   BOOL CALLBACK TerminateAppEnum( HWND hwnd, LPARAM lParam ) ;

   BOOL CALLBACK Terminate16AppEnum( HWND hwnd, LPARAM lParam ) ;

   /*----------------------------------------------------------------
   DWORD WINAPI TerminateApp( DWORD dwPID, DWORD dwTimeout )

   Purpose:
      Shut down a 32-Bit Process (or 16-bit process under Windows 95)

   Parameters:
      dwPID
         Process ID of the process to shut down.

      dwTimeout
         Wait time in milliseconds before shutting down the process.

   Return Value:
      TA_FAILED - If the shutdown failed.
      TA_SUCCESS_CLEAN - If the process was shutdown using WM_CLOSE.
      TA_SUCCESS_KILL - if the process was shut down with
         TerminateProcess().
      NOTE:  See header for these defines.
   ----------------------------------------------------------------*/
   DWORD WINAPI TerminateApp( DWORD dwPID, DWORD dwTimeout )
   {
      HANDLE   hProc ;
      DWORD   dwRet ;

      // If we can\'t open the process with PROCESS_TERMINATE rights,
      // then we give up immediately.
      hProc = OpenProcess(SYNCHRONIZE|PROCESS_TERMINATE, FALSE,
         dwPID);

      if(hProc == NULL)
      {
         return TA_FAILED ;
      }

      // TerminateAppEnum() posts WM_CLOSE to all windows whose PID
      // matches your process\'s.
      EnumWindows((WNDENUMPROC)TerminateAppEnum, (LPARAM) dwPID) ;

      // Wait on the handle. If it signals, great. If it times out,
      // then you kill it.
      if(WaitForSingleObject(hProc, dwTimeout)!=WAIT_OBJECT_0)
         dwRet=(TerminateProcess(hProc,0)?TA_SUCCESS_KILL:TA_FAILED);
      else
         dwRet = TA_SUCCESS_CLEAN ;

      CloseHandle(hProc) ;

      return dwRet ;
   }

   /*----------------------------------------------------------------
   DWORD WINAPI Terminate16App( DWORD dwPID, DWORD dwThread,
                        WORD w16Task, DWORD dwTimeout )

   Purpose:
      Shut down a Win16 APP.

   Parameters:
      dwPID
         Process ID of the NTVDM in which the 16-bit application is
         running.

      dwThread
         Thread ID of the thread of execution for the 16-bit
         application.

      w16Task
         16-bit task handle for the application.

      dwTimeout
         Wait time in milliseconds before shutting down the task.

   Return Value:
      If successful, returns TA_SUCCESS_16
      If unsuccessful, returns TA_FAILED.
      NOTE:  These values are defined in the header for this
      function.

   NOTE:
      You can get the Win16 task and thread ID through the
      VDMEnumTaskWOW() or the VDMEnumTaskWOWEx() functions.
   ----------------------------------------------------------------*/
   DWORD WINAPI Terminate16App( DWORD dwPID, DWORD dwThread,
                        WORD w16Task, DWORD dwTimeout )
   {
      HINSTANCE      hInstLib ;
      TERMINFO      info ;

      // You will be calling the functions through explicit linking
      // so that this code will be binary compatible across
      // Win32 platforms.
      BOOL (WINAPI *lpfVDMTerminateTaskWOW)(DWORD dwProcessId,
         WORD htask) ;

      hInstLib = LoadLibraryA( \"VDMDBG.DLL\" ) ;
      if( hInstLib == NULL )
         return TA_FAILED ;

      // Get procedure addresses.
      lpfVDMTerminateTaskWOW = (BOOL (WINAPI *)(DWORD, WORD ))
         GetProcAddress( hInstLib, \"VDMTerminateTaskWOW\" ) ;

      if( lpfVDMTerminateTaskWOW == NULL )
      {
         FreeLibrary( hInstLib ) ;
         return TA_FAILED ;
      }

      // Post a WM_CLOSE to all windows that match the ID and the
      // thread.
      info.dwID = dwPID ;
      info.dwThread = dwThread ;
      EnumWindows((WNDENUMPROC)Terminate16AppEnum, (LPARAM) &info) ;

      // Wait.
      Sleep( dwTimeout ) ;

      // Then terminate.
      lpfVDMTerminateTaskWOW(dwPID, w16Task) ;

      FreeLibrary( hInstLib ) ;
      return TA_SUCCESS_16 ;
   }

   BOOL CALLBACK TerminateAppEnum( HWND hwnd, LPARAM lParam )
   {
      DWORD dwID ;

      GetWindowThreadProcessId(hwnd, &dwID) ;

      if(dwID == (DWORD)lParam)
      {
         PostMessage(hwnd, WM_CLOSE, 0, 0) ;
      }

      return TRUE ;
   }

   BOOL CALLBACK Terminate16AppEnum( HWND hwnd, LPARAM lParam )
   {
      DWORD      dwID ;
      DWORD      dwThread ;
      TERMINFO   *termInfo ;

      termInfo = (TERMINFO *)lParam ;

      dwThread = GetWindowThreadProcessId(hwnd, &dwID) ;

      if(dwID == termInfo->dwID && termInfo->dwThread == dwThread )
      {
         PostMessage(hwnd, WM_CLOSE, 0, 0) ;
      }

      return TRUE ;
   }

 


--------------------------------------------------------------------------------

Additional query words: Kill Exit Terminate Program Application Process
Task
Keywords : BseProcThrd
Version : WINNT:4.0
Platform : Win95 winnt
Issue type : kbhowto


THE INFORMATION PROVIDED IN THE MICROSOFT KNOWLEDGE BASE IS PROVIDED \"AS IS\" WITHOUT WARRANTY OF ANY KIND. MICROSOFT DISCLAIMS ALL WARRANTIES, EITHER EXPRESS OR IMPLIED, INCLUDING THE WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. IN NO EVENT SHALL MICROSOFT CORPORATION OR ITS SUPPLIERS BE LIABLE FOR ANY DAMAGES WHATSOEVER INCLUDING DIRECT, INDIRECT, INCIDENTAL, CONSEQUENTIAL, LOSS OF BUSINESS PROFITS OR SPECIAL DAMAGES, EVEN IF MICROSOFT CORPORATION OR ITS SUPPLIERS HAVE BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. SOME STATES DO NOT ALLOW THE EXCLUSION OR LIMITATION OF LIABILITY FOR CONSEQUENTIAL OR INCIDENTAL DAMAGES SO THE FOREGOING LIMITATION MAY NOT APPLY.

Last reviewed: January 7, 1998
? 1998 Microsoft Corporation. All rights reserved. Terms of Use.
 

Tom_lyd
驱动大牛
驱动大牛
  • 注册日期2001-09-02
  • 最后登录2016-01-09
  • 粉丝0
  • 关注0
  • 积分10分
  • 威望1点
  • 贡献值0点
  • 好评度1点
  • 原创分0分
  • 专家分0分
地下室#
发布于:2002-06-04 10:02
做一个socket驱动, socket创建一个socket结构(自定义)问题是如果上层的应用程序非正常退出(被杀死), 则该内存将永远保留, 除非重启,

那位高手知道如何避免, 在进程被杀死时有什么事件通知驱动?



[编辑 -  6/3/02 by  pzm]


也许这不是一个好办法,但是可以达到目的。(你的这块内存是在内核中分配的吧!)
采用定时的机制:驱动程序创建一个定时器,并和应用程序共享一个事件对象,然后驱动程序在定时例程中触发这个事件对象,应用程序端专开一个线程来检测这个事件对象的状态,当为有信号态时,就通过IOCTL或者另外一个事件对象通知驱动程序收到信号。如果在一定的超时值范围内驱动程序没有得到应用程序的回应,就基本上可以判断应用程序处于未响应状态或者已被杀死。(在我的当前项目中我就是采用了这种办法。)
另一种办法,我没有试过,不知道是否真的有用,就是采用监控特定进程的消息。你可以访问这个链接查看详情(见附件)



附件名称/大小 下载次数 最后更新
2002-06-04_ProcessMonitor.htm (37KB)  1
Tom_lyd
游客

返回顶部