Aquí hay una cita directa de Essential Linux Device Drivers que podría ser lo que estás buscando. Parece que la parte dedicada a la UCR al final puede ser lo que le interesa.
Cerraduras lector-grabador de
Otro mecanismo de regulación de concurrencia especializada es una variante de un lector-grabador de spinlocks. Si el uso de una sección crítica de es tal que los subprocesos separados leen o escriben en una estructura de datos compartida, pero no hacen , estos bloqueos son naturales. Múltiples hilos de lectura están permitidos dentro de una región crítica simultáneamente. spinlocks Reader se definen como sigue:
rwlock_t myrwlock = RW_LOCK_UNLOCKED;
read_lock(&myrwlock); /* Acquire reader lock */
/* ... Critical Region ... */
read_unlock(&myrwlock); /* Release lock */
Sin embargo, si un hilo escritor entra en una sección crítica, otros hilos lector o escritor no están permitidos dentro. Para utilizar spinlocks escritor, que iba a escribir esto:
rwlock_t myrwlock = RW_LOCK_UNLOCKED;
write_lock(&myrwlock); /* Acquire writer lock */
/* ... Critical Region ... */
write_unlock(&myrwlock); /* Release lock */
mirar el código de enrutamiento IPX presente en net/ipx/ipx_route.c
para un ejemplo real de un spinlock un lector-grabador. Un bloqueo de lector-escritor llamado ipx_routes_lock
protege la tabla de enrutamiento IPX del acceso simultáneo.Los hilos que necesitan buscar la tabla de enrutamiento para reenviar paquetes solicitan bloqueos de lector. Los subprocesos que deben agregar o eliminar entradas de la tabla de enrutamiento adquieren bloqueos de escritor. Esto mejora el rendimiento porque generalmente hay muchas más instancias de búsquedas en la tabla de enrutamiento que las actualizaciones de la tabla de enrutamiento.
Como spinlocks regulares, bloqueos lector-grabador también tienen IRQ correspondientes variantes, a saber: read_lock_irqsave()
, read_lock_irqrestore()
, write_lock_irqsave()
, y write_lock_irqrestore()
. La semántica de estas funciones son similares a las de los spinlocks normales.
Los bloqueos de secuencia o seqlocks, introducidos en el kernel 2.6, son bloqueos lector-escritor donde los escritores son favorecidos por sobre los lectores . Esto es útil si las operaciones de escritura en una variable superan con creces los accesos de lectura. Un ejemplo es la variable jiffies_64
explicada anteriormente en este capítulo. Los hilos de Writer no esperan a los lectores que pueden estar dentro de en una sección crítica. Debido a esto, las discusiones lector puede descubrir que su entrada dentro de una sección crítica no ha logrado y puede que tenga que volver a intentar:
u64 get_jiffies_64(void) /* Defined in kernel/time.c */
{
unsigned long seq;
u64 ret;
do {
seq = read_seqbegin(&xtime_lock);
ret = jiffies_64;
} while (read_seqretry(&xtime_lock, seq));
return ret;
}
escritores proteger las regiones más importantes usando write_seqlock()
y write_sequnlock()
.
el kernel 2.6 introdujo otro mecanismo llamado Leer-Copy Update (RCU), que los rendimientos mejoraron el rendimiento cuando los lectores son mucho más numerosos escritores. La idea básica es que los hilos lectores pueden ejecutarse sin bloqueando. Los hilos del escritor son más complejos. Realizan operaciones de actualización en una copia de la estructura de datos y reemplazan el puntero que ven los lectores. La copia original se mantiene hasta que el siguiente contexto encienda todas las CPU a para garantizar la finalización de todas las operaciones de lectura en curso. Tenga en cuenta que el uso de RCU es más complicado que utilizar las primitivas discutidas hasta el momento y debe usarse solo si está seguro de que es la herramienta adecuada para el trabajo. Las estructuras y funciones de interfaz RCU se definen en include/linux/rcupdate.h
. Hay amplia documentación en Documentation/RCU/*
.
Para un ejemplo de uso UCR, un vistazo a fs/dcache.c
. En Linux, cada archivo está asociado con la entrada de directorio información (almacenada en una estructura llamada dentry), información de metadatos (almacenada en un inodo) y datos reales (almacenados en bloques de datos). Cada vez que opera en un archivo, los componentes en la ruta del archivo se analizan y se obtienen las anotaciones correspondientes . Las dentries se guardan en caché en una estructura de datos llamada dcache, al agilizar las operaciones futuras. En cualquier momento, el número de consultas de caché es mucho más que las actualizaciones de caché, por lo que las referencias al caché están protegidas utilizando primitivas de RCU.
No conozco la respuesta a esta pregunta, pero el libro "Understanding the Linux Kernel" tiene mucha información buena sobre este tipo de cosas. Es un gran libro, cualquiera que haga un trabajo de kernel debería leerlo. – Zifre
No sé mucho acerca de las funciones internas de concurrencia del kernel, pero puede hacer las suyas propias con el recuento de lector/escritor y bloqueos en writer-wait. –
@Nir Me alegra ver que finalmente aceptó una respuesta después de 4 años :-) –