Desarrollo de clústeres de Windows: 6) Escritura de archivos DLL de recursos
Escritura de una DLL de recursos
Introducción
Puede escribir una DLL de recursos personalizada utilizando el sistema de desarrollo MS Visual C++ u otras herramientas de desarrollo C/C++.
Versión del compilador MIDL (el compilador MIDL se proporciona en el SDK)
Versión de la biblioteca de plantillas activas (ATL) (necesaria para ampliar el código de muestra y el código generado por el tipo de recurso Versión del Asistente de generación)
Al configurar un entorno de compilación, consulte el SDK de la plataforma, especialmente los capítulos "Preparación del entorno de compilación" y "Notas del desarrollador". Capítulo de notas de entorno y desarrolladores
También se puede encontrar una implementación de referencia completa de la DLL de recursos en los ejemplos del SDK de plataforma (consulte SMB *** p)
Creación de nuevos tipos de recursos
p>Para crear un nuevo tipo de recurso, debe escribir una DLL de recurso y una DLL de extensión del administrador de clúster. Una forma sencilla de crear una DLL de recurso es ejecutar el Asistente de generación de tipos de recursos, que generará el esqueleto de la DLL del recurso y/o la DLL de extensión del Administrador de clústeres, incluidas definiciones de puntos de entrada, declaraciones y exportaciones.
Información completa sobre la creación de una DLL de recurso Para conocer los pasos, consulte la documentación del SDK "Creación de un tipo de recurso personalizado utilizando el AppWizard de tipo de recurso" y "Personalizar el AppWizard de tipo de recurso".
El marco de DLL de recursos generado contiene solo la funcionalidad de conmutación por error y conmutación por recuperación más básica; para utilizar la funcionalidad completa de un entorno en clúster y permitir que la DLL proporcione información específica de los recursos, debe escribir su propio código. Como se describe a continuación, necesitará utilizar la API de recursos para realizar la mayoría de las operaciones personalizadas
DLL de recursos personalizados
Como se mencionó anteriormente, la API de recursos contiene varias implementaciones en la DLL de recursos La entrada Funciones puntuales que Resource Monitor utiliza para administrar los recursos proporcionados por la DLL. Resource Monitor utiliza estas funciones de punto de entrada para administrar los recursos proporcionados por la DLL. Además, el monitor de recursos implementa funciones de devolución de llamada que utiliza la DLL de recursos para informar el estado al servicio de clúster o registrar eventos para el administrador del sistema.
La mayoría de las funciones de punto de entrada son necesarias para todos los recursos. Las funciones de punto de entrada restantes se enumeran a continuación y sus detalles se analizarán en este artículo. Iniciar Abrir en línea LooksAlive IsAlive Sin conexión Cerrar Terminar ResourceControl ResourceTypeControl
Cada DLL de recurso compatible con el software del clúster debe seguir estas pautas
DLL de recursos Hay una excepción a la regla de que una determinada instancia de recurso no es reentrante, y es la función de punto de entrada de terminación. La DLL de recursos es reentrante a otros ID de recursos. Si la DLL de recursos tiene más de una ID de recursos, la DLL de recursos debe sincronizar todos los datos globales disfrutados en la DLL.
En la DLL de recursos. , entrada La función de punto no debería tardar más de milisegundos en completar una operación. Si una función de punto de entrada (especialmente LooksAlive o isAlive en línea sin conexión) excede este límite, se debe generar un hilo para manejar la operación que requiere mucho tiempo (tenga en cuenta que el asistente actual genera un hilo para en línea, y las versiones futuras también deberían generar para fuera de línea). un hilo).
Durante el proceso de inicialización de la DLL de recursos, la función de punto de entrada de la DLL (el punto de entrada estándar de la DLL después de que el sistema carga la DLL) se llamará con el indicador DLL_PROCESS_ATTACH y luego el monitor de recursos comenzará a llamar. la función de punto de entrada de la API de recursos.
Rutina de inicio
Después de cargar la DLL del recurso, el monitor de recursos comienza a llamar a la función de punto de entrada de la API del recurso.
Una vez cargada la DLL de recursos, el monitor de recursos llama a la rutina de inicio. Tenga en cuenta que solo se exporta la función del punto de entrada de inicio. Se accede a todas las demás funciones de punto de entrada implementadas en la DLL de recursos a través de la tabla de funciones devuelta por el Inicio.
La siguiente es la definición de la rutina de inicio DWORD WINAPI Startup (LPCWSTR ResourceType DWORD MinVersionSupported DWORD MaxVersionSupported PSET_RESOURCE_STATUS_ROUTINE SetResourceStatus PLOG_EVENT_ROUTINE LogEvent PCLRES_FUNCTION_TABLE * FunctionTable
El parámetro ResourceType identifica el tipo de recurso que se está ejecutando; iniciado
SetResourceStatus y LogEvent son funciones de devolución de llamada implementadas por el monitor de recursos (que se analizan más adelante en este documento). Si la DLL del recurso tarda más de milisegundos después de llamar a una función de punto de entrada en línea o fuera de línea, debe llamar a SetResourceStatus para notificar al clúster sobre el estado del recurso (estas funciones de devolución de llamada se analizan más adelante en este documento). Las DLL de recursos también deben usar LogEvent para informar eventos y errores. Las DLL de recursos también deben usar LogEvent para informar eventos y errores (SetResourceStatus debe llamarse solo en línea o fuera de línea, y solo cuando en línea o fuera de línea devuelve ERROR_IO_PENDING; consulte la discusión sobre en línea y fuera de línea para obtener más información)
La estructura FunctionTable contiene las direcciones de las funciones de punto de entrada restantes del recurso DLL.
Tenga en cuenta que al iniciar el recurso DLL de función de punto de entrada se debe llamar a SetResourceStatus para notificar al clúster sobre el estado del recurso. La función de punto de entrada de inicio es el único lugar donde la DLL de recursos guarda las funciones de devolución de llamada LogEvent y SetResourceStatus
El inicio devuelve los siguientes valores
Si la solicitud tiene éxito, devuelve ERROR_SUCCESS
Si las funciones de recurso en MinVersionSupported y MaxVersionSupported no son compatibles y devuelven ERROR_REVISION_MISMATCH
Si la operación no tiene éxito, se devuelve un valor de error de interfaz de programación Win
Para optimizar las operaciones de recursos, asegúrese de iniciar la ejecución en milisegundos. Completado para la unidad
Rutina abierta
Normalmente, una vez que el inicio regresa exitosamente, el Monitor de recursos llamará a la función Abrir punto de entrada para cada recurso administrado por la DLL de recursos
La rutina de apertura se define de la siguiente manera. Lo siguiente es RESID WINAPI Open (LPCWSTR ResourceName HKEY ResourceKey RESOURCE_HANDLE ResourceHandle);
El parámetro ResourceName se utiliza para identificar el recurso que se está abriendo (una DLL de recurso puede proporcionar múltiples recursos de un tipo determinado). El parámetro ResourceKey es información específica sobre el recurso, es privado y reside en la base de datos del clúster. Cuando Open regresa, la clave se cerrará, por lo que si el recurso accede a la clave en otra función de punto de entrada, la DLL debe llamar a ClusterRegOpenKey o ClusterRegCreateKey. El parámetro ResourceHandle se utiliza en las funciones de devolución de llamada SetResourceStatus y LogEvent.
Open utiliza la API del clúster para abrir la base de datos del clúster y obtener parámetros de recursos y propiedades privadas.
Una cosa importante para recordar es que la DLL del recurso debe verificar en el punto de entrada Abrir si el recurso está actualmente fuera de línea (un recurso no puede estar en línea en varios nodos al mismo tiempo). El punto importante es que la DLL del recurso debe verificar en el punto de entrada Abrir si el recurso está actualmente fuera de línea (el recurso no puede estar en línea en varios nodos al mismo tiempo) y, si el recurso está actualmente en línea, la DLL debe intentar tomar está fuera de línea (tenga en cuenta que, en este caso, en línea y fuera de línea se refieren al estado de la aplicación o servicio, no a un nodo del clúster determinado; el recurso debe estar realmente fuera de línea y no ser propiedad de un nodo). Cree una estructura de datos dedicada para el recurso
Tenga en cuenta que si el recurso es un recurso de quórum, la API del clúster no está disponible en la rutina Open
Open devuelve el siguiente valor
Si la operación tiene éxito, devolverá el identificador de recurso (RESID)
Si la operación no tiene éxito, devolverá NULL y se debe llamar para indicar que ocurrió un error
Se debe llamar a SetLastError para indicar que ocurrió un error
Se debe llamar a la DLL del recurso para indicar que el recurso es un recurso. Si Open devuelve un error (devuelve NULL), el recurso no se puede administrar, por lo que Open solo debería devolver un error en casos bastante raros (por ejemplo, no se puede asignar memoria para el recurso)
Por razones de optimización de recursos , asegúrese de que la ejecución de Open se complete en milisegundos
Rutinas en línea
Cuando se abre el recurso, el monitor de recursos llamará Cuando se abre el recurso, el monitor de recursos llamará la entrada en línea Haga clic en la función para poner el recurso en línea
La definición de la rutina en línea es la siguiente: DWORD WINAPI Online (RESID ResourceId PHANDLE EventHandle
El parámetro ResourceId pasado a); la función de punto de entrada es el identificador único del símbolo del recurso (igual que Abrir). La DLL de recursos puede devolver el parámetro EventHandle al monitor de recursos para notificar de forma asíncrona al monitor de recursos su estado. Si el parámetro EventHandle no es un identificador válido que pueda monotonizarse, el monitor de recursos llamará periódicamente a la función de entrada EventHandle de la DLL del recurso para verificar el estado del recurso. Si no desea que este método interfiera con el recurso, la DLL debe devolver un identificador válido en el parámetro EventHandle. Esta implementación diferente es necesaria porque diferentes tipos de recursos tienen diferentes necesidades. Por ejemplo, los discos en línea son completamente diferentes de las aplicaciones normales en línea. Poner un disco en línea implica operaciones como montar el disco y verificar la firma del disco, pero poner la aplicación en línea solo requiere una simple llamada a CreateProcess
Online devuelve el siguiente contenido
Si el la operación es exitosa y el recurso ha estado en línea, se devuelve ERROR. Si la operación es exitosa y el recurso ahora está en línea, devuelva ERROR_SUCCESS
Si el recurso es exclusivo de otros sistemas y uno de los sistemas tiene derechos exclusivos, devuelva ERROR_RESOURCE_NOT_AVAILABLE
Si la solicitud está en estado pendiente y se ha activado un subproceso para manejar la solicitud, devuelve ERROR_SUCCESS y devuelve ERROR_IO_PENDING
Si la operación no tiene éxito, Online devuelve el valor de error de Win
Para optimizar las operaciones de recursos , asegúrese de que el ejemplo en línea La implementación del proceso pueda completar el procesamiento en milisegundos, pero si no puede, debe devolver ERROR_IO_PENDING al recurso inmediatamente después de generar el subproceso de trabajo para poner el recurso en línea. Monitoreo La función de devolución de llamada SetResourceStatus (cuya dirección se almacena en la función de entrada de inicio) debe llamarse periódicamente para mostrar el estado del recurso. Una vez que el recurso se conecta, el subproceso de trabajo debe cancelarse o pausarse para su uso futuro.
Si por alguna razón el recurso no se conecta, la DLL del recurso debe registrar el evento usando la función de devolución de llamada LogEvent y llamar a la función SetResourceStatus. Código de estado ClusterResourceOnline
Fuera de línea - Código de estado ClusterResourceOffline
Fallido - Código de estado ClusterResourceFailed
Esperando conectarse - Código de estado ClusterResourceOnlinePending
Esperando estar fuera de línea: código de estado ClusterResourceOfflinePending
SDK Para obtener más información sobre SetResourceStatus, consulte Platform SDK
Si el recurso no está en línea después de unos minutos, el monitor de recursos llamará a la entrada de terminación para cancelar la operación. Si el recurso tarda más de unos minutos en conectarse, puede utilizar el archivo ejecutable del clúster en la API del clúster del Administrador de clústeres u otras herramientas de administración. ClusterResourceControl Modifica la propiedad pública PendingTimeout usando el código de control CLUSCTL_RESOUCE_SET_M_PROPERTIES (consulte la documentación del SDK de la plataforma para obtener más información sobre el código de control del clúster, propiedades públicas, propiedades privadas, etc.)
Rutinas LooksAlive e IsAlive
Una vez que el recurso esté en línea, el monitor de recursos verificará periódicamente el estado del recurso. Resource Monitor utiliza los puntos de entrada LooksAlive e IsAlive para hacer esto.
Rutina LooksAlive La rutina LooksAlive se define de la siguiente manera: BOOL WINAPI LooksAlive (RESID ResourceId
La rutina IsAlive se define de la siguiente manera: BOOL WINAPI IsAlive (RESID ResourceId ); p >
En ambas rutinas, el parámetro ResourceId identifica de forma única la instancia de recurso que se está inspeccionando. Normalmente, LooksAlive se utiliza para comprobaciones simples (por ejemplo, comprobar si el proceso todavía se está ejecutando, si el archivo todavía existe, etc.), y el administrador de recursos puede llamar a LooksAlive periódicamente. Si no desea que la DLL de recursos lo interrumpa, puede devolver un EventHandle válido al monitor de recursos en la rutina en línea (como se describe anteriormente) y luego usar ese identificador para enviar llamadas al monitor de recursos. Este identificador se utilizará para notificar al monitor de recursos el estado del recurso.
La función de entrada IsAlive realizará un cálculo más detallado del estado del recurso y será ejecutada por el monitor de recursos (no puede). bloquearse). Las DLL de recursos deben verificarse minuciosamente para ver si el recurso funciona correctamente. Por ejemplo, los recursos de la base de datos deben verificar si la base de datos puede escribir en el disco, realizar consultas y actualizaciones, etc.
El valor de retorno de LooksAlive es el siguiente
Si el recurso está en línea y disponible, se devuelve VERDADERO
Si el recurso no funciona, FALSO es. devuelto El valor de retorno de LooksAlive es el siguiente
p>
El valor de retorno de IsAlive es el siguiente
Si el recurso está en línea y funciona normalmente, devuelve VERDADERO <. /p>
Si el recurso no funciona correctamente, devuelve FALSO
Para fines de optimización, la función de punto de entrada de IsAlive debe completarse en milisegundos. Como se mencionó anteriormente, se debe crear un subproceso de trabajo separado para realizar el trabajo de verificar el recurso, y luego el subproceso de trabajo debe eliminar el estado para que IsAlive pueda obtener el estado y devolverlo al administrador de recursos.
Tenga en cuenta que LooksAlive no se utiliza en ningún caso. En ningún caso debe exceder los milisegundos y, en la mayoría de los casos, no debe exceder los milisegundos.
IsAlive tarda un poco más, pero incluso si es una llamada asincrónica, otras funciones de entrada de recursos administradas por el monitor de recursos en el mismo hilo esperarán el regreso directo de IsAlive. Derivar de un hilo no mejora la situación, por lo que IsAlive no debería tardar más de milisegundos en completarse, por lo que debería completarse en no más de milisegundos.
Rutinas fuera de línea
Hasta ahora, la discusión sobre las funciones de entrada ha sido sobre personalizar una buena DLL de recursos desde el kernel. Las siguientes funciones de entrada proporcionan un mecanismo de cierre y descarga de recursos. es la función fuera de línea
La función fuera de línea se define de la siguiente manera: DWORD WINAPI Fuera de línea (RESID ResourceId
El parámetro ResourceId identifica de forma única el recurso); Cuando el recurso está fuera de línea, el monitor de recursos llama a esta función de entrada.
Sin conexión devuelve los siguientes valores
Si la solicitud de recurso sin conexión se completa con éxito, se devuelve ERROR_SUCCESS
Si la solicitud de recurso sin conexión se completa con éxito, ERROR_SUCCESS se devuelve
La primera función de entrada se define de la siguiente manera. ÉXITO
Si la solicitud aún está pendiente y se ha activado un hilo para manejar la solicitud fuera de línea, devuelva ERROR_IO_PENDING
Si la operación no se puede completar por otros motivos, si la ejecución de la la rutina fuera de línea excede Si se excede este límite, se debe devolver ERROR_IO_PENDING y se debe generar un hilo para completar la solicitud fuera de línea. Este hilo debe usar la devolución de llamada SetResourceStatus para actualizar continuamente el estado del recurso en el monitor de recursos hasta que el estado del recurso sea ClusterResourceOffline
Si el recurso no se cierra correctamente dentro del tiempo de espera de PendingTimeout, se debe devolver un código de error Win
La DLL del recurso debería cerrar correctamente el recurso en milisegundos y regresar desde esta entrada. Si el recurso no se cierra correctamente dentro del tiempo de espera de PendingTimeout, o la función fuera de línea devuelve un código de error Win, el monitor de recursos llamará a la función Terminar entrada para finalizar forzosamente el recurso
Rutina de apagado
Cerrar La función de entrada se utiliza para cerrar recursos y solo se puede llamar una vez para un recurso.
Una estructura asignada por la función de entrada Open Offline ResourceControl o ResourceTypeControl. Si el recurso que se va a cerrar no está fuera de línea, llame a Terminate para forzarlo a estar fuera de línea
La rutina de cierre se define de la siguiente manera: VOID WINAPI Close (RESID ResourceId). );
El parámetro ResourcdId es el identificador único del recurso que se está cerrando
Cerrar no tiene valor de retorno
La DLL del recurso debe cerrar el recurso en milisegundos. pero si se excede este límite,
Rutina
La función de entrada de terminación finaliza inmediatamente el proceso que no se cierra correctamente cuando se llama sin conexión
La rutina de terminación es definido de la siguiente manera VOID WINAPI Terminate (RESID ResourceId);
ResourceId es el identificador único del recurso que se fuerza a desconectarse si el recurso DLL tiene un subproceso esperando para desconectar el recurso o desconectarlo correctamente. , abortará la operación fuera de línea del subproceso y forzará que el recurso esté fuera de línea
Terminar no tiene valor de retorno
Rutinas ResourceControl y ResourceTypeControl
La entrada ResourceControl y ResourceTypeControl Las funciones son opcionales, pero Microsoft recomienda implementarlas para admitir herramientas de administración de código de control de recursos del clúster, como Cluster Manager y Cluster Exe, y aplicaciones compatibles con clústeres que utilizan las rutinas ClusterResourceControl y ClusterResourceTypeControl. La función ClusterResourceTypeControl se utiliza para comunicar información de exclusividad con los recursos. Por ejemplo, estas funciones se pueden utilizar para establecer propiedades (públicas y privadas), solicitar operaciones y más. Cuando un administrador o una aplicación compatible con clústeres llama a cualquiera de las funciones ClusterResourceXXXXControl, el administrador de recursos llama a ResourceControl o ResourceResourceTypeControl respectivamente. El administrador de recursos llamará a ResourceControl o ResourceTypeControl respectivamente, pasando el código de control correcto, y la DLL de recursos que implementa estas dos rutinas realizará solicitudes de control o establecerá propiedades de recursos según el código de control.
La rutina ResourceControl se define de la siguiente manera DWORD WINAPI ResourceControl (RESID ResourceId DWORD ControlCode LPVOID InBuffer DWORD InBufferSize LPVOID OutBuffer DWORD OutBufferSize LPDWORD BytesReturned
El parámetro ResourceId es el identificador del afectado); recurso ControlCode representación El código de control para realizar la operación. ControlCode representa el código de control para realizar la operación; para obtener una lista de valores válidos para este parámetro, consulte la sección "Códigos de control de recursos" del SDK de la plataforma
InBuffer es un puntero al búfer de datos entrantes utilizado por la operación. Tenga en cuenta que InBuffer y OutBuffer pueden estar vacíos si la operación no requiere ni devuelve datos.
BytesReturned es el número de bytes de datos reales en OutBuffer.
ResourceControl devuelve los siguientes valores.
Los siguientes valores
ERROR_SUCCESS si la operación especificada por ControlCode se completó exitosamente (aunque el valor de retorno real depende del código de control)
ERROR_INVALID_ si la DLL del recurso no admite la operación indicada por ControlCode, o la solicitud debe ser realizada por el Monitor de recursos que maneja. Función
Si la operación no tiene éxito, se devuelve el código de error Win
La rutina ResourceTypeControl se define de la siguiente manera DWORD WINAPI ResourceTypeControl ( LPCWSTR ResourceTypeName DWORD ControlCode LPVOID InBuffer DWORD InBufferSize LPVOID OutBuffer DWORD OutBufferSize LPDWORD BytesReturned );
ResourceTypeName es el identificador del tipo de recurso afectado por la operación. ResourceTypeName es el identificador del tipo de recurso afectado por la operación ControlCode es el código de control de la operación a realizar. Para obtener una lista de valores válidos para el parámetro ControlCode, consulte la sección Códigos de control de recursos del SDK de plataforma.
InBuffer es un puntero al búfer de datos entrantes utilizado por la operación. InBufferSize es el tamaño, en bytes, del búfer utilizado por la operación. OutBuffer es un puntero al búfer de datos devuelto por la operación OutBufferSize es su tamaño en bytes. Tenga en cuenta que InBuffer y OutBuffer pueden ser NULL si la operación no requiere ni devuelve datos.
BytesReturned es OutBuffer El tamaño real de los datos del resultado devueltos en el búfer. BytesReturned es el tamaño real de los datos de resultado devueltos en el búfer OutBuffer
ResourceTypeControl devuelve lo siguiente
Si la operación indicada por ControlCode se completa correctamente, ResourceTypeControl devuelve ERROR_SUCCESS (aunque el valor de retorno real depende del código de control)
Si el recurso DLL no lo admite, ResourceCode devuelve ERROR_SUCCESS. p> Si la DLL del recurso no admite la operación indicada por el Código de control o la solicitud debe ser manejada por el monitor de recursos, se devuelve ERROR_INVALID_FUNCTIONlishixinzhi/Article/program/net/201311/13753.