Los rincones del API Win32: Archivos proyectados en memoria - Objetos del núcleo
Tutorial creado por Juan Manuel. Extraido de: http://www.lawebdejm.com
27 de Agosto de 2005
Programación estructurada
13 - Objetos del núcleo
¿Y por qué vamos a hablar de objetos del núcleo en un artículo sobre archivos proyectados? Pues porque los archivos proyectados son un tipo de objetos de núcleo, y es muy importante comprender el funcionamiento de los objetos del núcleo para entender a los archivos proyectados.
Estos objetos son un tipo especial dentro de todos los que podemos crear dentro del sistema Win32. Básicamente, Win32 tiene tres tipos de objetos:
Todos ellos se identifican por un descriptor (el famoso handle), aunque el significado de este descriptor es muy distinto dependiendo del tipo de objeto (puede ser un puntero, un índice de un tabla, etc.).
Los objetos del núcleo son un grupo de objetos con ciertas características especiales. La principal de ellas es que se almacenan en una tabla interna al proceso. Cada vez que se crea un objeto del núcleo, se busca una entrada libre en esta tabla y se retorna la posición que ocupa. Esa posición (el índice) será el descriptor del objeto. Esta es la razón por la que los descriptores del objetos del núcleo suelen ser números bajos, mientras que los descriptores de objetos de usuario o GDI son número altos (porque son direcciones de memoria).
Un proceso tendrá acceso a los objetos del núcleo que aparezcan en su tabla de objetos, aunque él no los haya creado.
Dentro de estos objetos del núcleo tenemos: archivos, variables de entorno, procesos, hilos, mutex, eventos, semáforos, tuberías y proyecciones de archivo.
Cada objeto del núcleo tiene una función específica para su creación, normalmente CreateXXX (donde XXX es el nombre del objeto): CreateFile, CreateFileMapping, CreateSemaphore, CreateMutex, etc.
Básicamente, lo que se hace durante la creación de un objeto del núcleo es crear una nueva entrada en la tabla de objetos, y retornar el índice asociado. Además, en la misma tabla se marcan las propiedades de cada objeto, como sus atributos de seguridad, si es heredable etc.
En cada una de estas funciones, tenemos un parámetro que es un puntero a una estructura de tipo SECURITY_ATTRIBUTES. Este es, precisamente, el atributo que controla si el descriptor a crear va a ser heredado o no por los subprocesos. Esta estructura se define del siguiente modo:
typedef struct _SECURITY_ATTRIBUTES { DWORD nLength; LPVOID lpSecurityDescriptor; BOOL bInheritHandle; } SECURITY_ATTRIBUTES;
Además de la creación de objetos, en algunos casos es posible la apertura de objetos previamente creados, a través de funciones OpenXXX (como nuestra amiga OpenFileMapping). Estas funciones, lo que hacen es copiar la entrada correspondiente de la tabla de objetos del proceso creador (algo así como forzar la herencia).
Cada objeto del núcleo cuenta con un contador de referencias, que no es más que un valor que indica la cantidad de procesos que tienen acceso al objeto. Cuando se crea un objeto del núcleo, se añade la entrada a la tabla de objetos y se marca el contador con 1. Cada vez que el objeto se hereda o abre desde otro proceso, el contador de referencias se incrementa en uno. Cuando ya no sea necesario utilizar un objeto del núcleo, debe cerrarse a través de una función genérica: CloseHandle. Esta función, lo que hace es eliminar la entrada en la tabla de objetos (aunque no el objeto en sí), y restar uno al contador de referencias. Cuando el contador de referencias de un objeto llega a 0, todos los recursos asociados al objeto se liberan y éste se considera destruido.
Esta es la razón por la que hay que llamar a CloseHandle siempre, hayamos creado o abierto el objeto, ya que debemos decrementar el contador de referencias, y será el sistema el encargado de liberar el objeto.
Este es el comportamiento que tienen los objetos de núcleo, y de él nos podemos aprovechar para la comunicación entre procesos.
Básicamente nos podemos comunicar con otros procesos con la siguientes métodos:
Estos objetos son un tipo especial dentro de todos los que podemos crear dentro del sistema Win32. Básicamente, Win32 tiene tres tipos de objetos:
- Objetos de usuario (como ventanas, menús, ganchos, etc.): son objetos identificados por un descriptor (que no suele ser más que la dirección de memoria donde comienza el objeto). Cualquier proceso que conozca el descriptor puede acceder al objeto en cuestión.
- Objetos gráficos o GDI (como el objeto Bitmap, Font, Pen, Brush, etc.): estos objetos son privados al proceso que los crea, aunque éste tiene disponibilidad total del objeto.
- Objetos del núcleo (como la proyecciones de archivo, hilos, etc.): son objetos gestionados por el núcleo del sistema operativo. Estos objetos pueden ser accedidos desde varios procesos, siempre y cuando se conozca el descriptor que los identifica.
Todos ellos se identifican por un descriptor (el famoso handle), aunque el significado de este descriptor es muy distinto dependiendo del tipo de objeto (puede ser un puntero, un índice de un tabla, etc.).
Los objetos del núcleo son un grupo de objetos con ciertas características especiales. La principal de ellas es que se almacenan en una tabla interna al proceso. Cada vez que se crea un objeto del núcleo, se busca una entrada libre en esta tabla y se retorna la posición que ocupa. Esa posición (el índice) será el descriptor del objeto. Esta es la razón por la que los descriptores del objetos del núcleo suelen ser números bajos, mientras que los descriptores de objetos de usuario o GDI son número altos (porque son direcciones de memoria).
Un proceso tendrá acceso a los objetos del núcleo que aparezcan en su tabla de objetos, aunque él no los haya creado.
Dentro de estos objetos del núcleo tenemos: archivos, variables de entorno, procesos, hilos, mutex, eventos, semáforos, tuberías y proyecciones de archivo.
Cada objeto del núcleo tiene una función específica para su creación, normalmente CreateXXX (donde XXX es el nombre del objeto): CreateFile, CreateFileMapping, CreateSemaphore, CreateMutex, etc.
Básicamente, lo que se hace durante la creación de un objeto del núcleo es crear una nueva entrada en la tabla de objetos, y retornar el índice asociado. Además, en la misma tabla se marcan las propiedades de cada objeto, como sus atributos de seguridad, si es heredable etc.
En cada una de estas funciones, tenemos un parámetro que es un puntero a una estructura de tipo SECURITY_ATTRIBUTES. Este es, precisamente, el atributo que controla si el descriptor a crear va a ser heredado o no por los subprocesos. Esta estructura se define del siguiente modo:
typedef struct _SECURITY_ATTRIBUTES { DWORD nLength; LPVOID lpSecurityDescriptor; BOOL bInheritHandle; } SECURITY_ATTRIBUTES;
- nLength: indica el tamaño de la estructura. Se debe asignar siempre el valor sizeof(Estructura). A modo de curiosidad: este tipo de campos es muy habitual encontrárselos en las estructuras definidas en Win32 y su principal misión es detectar distintas versiones de la estructura durante la ejecución. Dentro del código de las funciones que utilizan esas estructuras, se comprueba el tamaño, y dependiendo de su valor, se puede deducir que versión de estructura se está utilizando, y actuar en consecuencia.
- lpSecurityDescriptor: es un puntero a una estructura de tipo SECURITY_DESCRIPTOR, que representa la seguridad que se le dará al objeto (qué usuarios podrán acceder, con qué permisos, etc.). Indicando un NULL, se asignará el descriptor de seguridad por defecto. Este atributo sólo tiene sentido en sistemas NT/2000/XP, ya que Windows 95/98/Me no soporta seguridad. No vamos a entrar en este tema, ya que no sé decir mucho más sobre esto. (-:
- bInheritHandle: este es el campo más importante. Indica si el descriptor es heredable. La herencia de descriptores se basa en que, cuando un descriptor se marca como heredable, éste se copiará a la tabla de objetos en cada proceso hijo que sea creado. Es decir, cuando llamamos a CreateProcess desde un proceso, Win32 recorre la tabla del proceso padre (el que llama a CreateProcess), y copia cada una de las entradas que han sido marcadas como heredable a la tabla del proceso hijo. Además, Win32 garantiza que cada entrada se copia en la misma posición que en la tabla-padre, es decir: conserva el descriptor.
Además de la creación de objetos, en algunos casos es posible la apertura de objetos previamente creados, a través de funciones OpenXXX (como nuestra amiga OpenFileMapping). Estas funciones, lo que hacen es copiar la entrada correspondiente de la tabla de objetos del proceso creador (algo así como forzar la herencia).
Cada objeto del núcleo cuenta con un contador de referencias, que no es más que un valor que indica la cantidad de procesos que tienen acceso al objeto. Cuando se crea un objeto del núcleo, se añade la entrada a la tabla de objetos y se marca el contador con 1. Cada vez que el objeto se hereda o abre desde otro proceso, el contador de referencias se incrementa en uno. Cuando ya no sea necesario utilizar un objeto del núcleo, debe cerrarse a través de una función genérica: CloseHandle. Esta función, lo que hace es eliminar la entrada en la tabla de objetos (aunque no el objeto en sí), y restar uno al contador de referencias. Cuando el contador de referencias de un objeto llega a 0, todos los recursos asociados al objeto se liberan y éste se considera destruido.
Esta es la razón por la que hay que llamar a CloseHandle siempre, hayamos creado o abierto el objeto, ya que debemos decrementar el contador de referencias, y será el sistema el encargado de liberar el objeto.
Este es el comportamiento que tienen los objetos de núcleo, y de él nos podemos aprovechar para la comunicación entre procesos.
Básicamente nos podemos comunicar con otros procesos con la siguientes métodos:
Valora este capítulo:
Autor y licencia de 'Los rincones del API Win32: Archivos proyectados en memoria - Objetos del núcleo'
|
Opiniona sobre 'Los rincones del API Win32: Archivos proyectados en memoria - Objetos del núcleo' (1)
Tu nombre debe tener tres caracteres como mínimo.
Es necesario que te des de alta con una cuenta de correo válida.
Es necesario que te des de alta con una cuenta de correo válida.
El contenido del título de tu opinión debe tener tres caracteres como mínimo.
Es obligatorio que selecciones una valoración del recurso.
El contenido del comentario de tu opinión debe tener tres caracteres como mínimo.
Opina sobre este tutorial |
Wikis relacionados con 'Los rincones del API Win32: Archivos proyectados en memoria - Objetos del núcleo'
Curso que profundiza en el gestor de montones (o montículos) dentro de Win32, así como...
Más »
UML (Unified Modeling Language) es un lenguaje que permite modelar, construir y documentar los elementos...
Más »
Aprenderás a utilizar uno de los mejores clientes P2P que actualmente existe (o sobrevive), a...
Más »
Con este articulo serás capaz de instalar el eMule en tu ordenador y comenzar a...
Más »
El Poeta posee la extraña capacidad para hablar sobre los orígenes. Digo "extraña" porque no...
Más »


