13 - Objetos del núcleo

[editar]
Tutorial creado por Juan Manuel. Extraido de: http://www.lawebdejm.com
30 de Noviembre de 1999
¿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:

  1. 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.
  2. 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.
  3. 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:
[editar]

1 opinión

Bien.

Cool.

Tutoriales relacionados con 'Los rincones del API Win32: Archivos proyectados en memoria'

Este curso trata el tema de la memoria en la plataforma Win32. En esta ocasión... Más »
Curso que profundiza en el gestor de montones (o montículos) dentro de Win32, así como... Más »
El protocolo FTP desde el API WinInet. Con este curso aprenderás a hacer un pequeño... Más »
Entramos en temas interesantes: el acceso a recursos remotos a través del protocolo de aplicación... Más »

Autor y licencia de 'Los rincones del API Win32: Archivos proyectados en memoria'


Tutorial de Juan Manuel. Extraido de: http://www.lawebdejm.com CopyLeft
Este contenido ha sido recopilado por el equipo de Wikilearning. Todo el contenido recopilado se ha obtenido respetando y comunicando en nuestro site la licencia de cada fuente.
Wikilearning tiene permiso expreso por escrito de los autores para publicar los contenidos que ha extraído de otras webs, incluyendo su uso comercial.