SearchUser loginSyndicate |
Novedades y cambios en 2.6.16 (es)Submitted by kernel-labs on Fri, 2006-03-24 20:34.
Tomando como base el excelente trabajo de kernelnewbies.org en kernelnewbies.org - LinuxChanges, vamos a presentar un resumen de los cambios más relevantes en la nueva versión del kernel Linux 2.6.16 (20 de Marzo del 2006). Para una lista completa de los mismos remitirse al documento anterior o al documento oficial
kernel.org - ChangeLog-2.6.16, este último en un formato menos comprensible para los no iniciados.
Nuevas *at syscallsLa incorporación de una nueva familia de system calls, las conocidas como *at syscalls, hacen a la serie 2.6 del kernel Linux bastante prolífica en la creación de nuevas llamadas al sistema, hecho este que suele tomarse con bastante cautela en la comunidad de desarrolladores del kernel Linux y en teoría sólo haciéndose efectivas estas adiciones cuando existe una necesidad real de ellas. El mundo Unix siempre se ha caracterizado por un conjunto bastante reducido de llamadas al sistema.Ulrich Drepper, mantenedor de la glibc, ha incorporado un conjunto de 13 llamadas al sistema del estilo de las siguientes: int open(const char *path, int oflag, /* mode_t mode */...);openat, mkdirat, mknodat, fchownat, futimesat, newfstatat, unlinkat, renameat, linkat, symlinkat, readlinkat, fchmodat, faccessat. Nuevas llamadas al sistema: pselect/ppollNuevas llamadas al sistema implementadas por David Woodhouse. Cada una de estas llamadas toma como parámetro una máscara de señal (signal mask), esa máscara será aplicada mientras el proceso que realiza la llamada espera por eventos, siendo restaurada la máscara anterior cuando retorne la llamada. El proceso por tanto podrá aplicar una máscara de señales distinta cuando esté esperando por entrada/salida, de esta forma podrá bloquear las señales que le interesen mientras que realiza la espera. Estas funciones están soportadas en la glibc, pero para una implementación robusta, se hacía necesario la correspondiente implementación en el kernel.Nueva llamada al sistema: unshare()Esta nueva llamada al sistema implementada por Janak Desai, permite a un proceso desconectar recursos propios que son compartidos con otros procesos. Cuando un nuevo proceso es creado con al llamada al sistema clone(), según los flags suministrados a la función se indicará al kernel qué recursos del proceso que hace la llamada deben compartirse con el hijo creado. Típicamente los recursos que se pueden compartir son el espacio de memoria virtual, los ficheros abiertos, manejadores de señales, etc. También, por defecto, los procesos hijos comparten el espacio de nombres del sistema de archivos visto por su padre (generalmente el namespace del sistema completo).Tradicionalmente en las versiones precedentes del kernel Linux, las decisiones de compartición de recursos hechas en la llamada clone() se mantenían durante todo el tiempo de vida del proceso afectado. No había ninguna razón para cambiar este conjunto de recursos compartidos, pero en recientes discusiones sobre el soporte de montaje privado de sistemas de archivos (con el parche para sistemas de archivos en espacio de usuario), se planteó si sería útil para un proceso ser capaz de dejar de compartir (unshare) recursos después de su creación. En particular, si un proceso podría desconectarse del espacio de nombres del sistema de archivos global y crear el suyo propio, pudiendo de esta manera crear los montajes privados que desease, creando así su propio namespace del sistema de archivos (su propia vista del sistema de archivos). Al final se ha incluido la llamada al sistema: int unshare(int flags);El argumento flags puede ser: CLONE_FILES: la tabla de descriptores (ficheros abiertos) del llamador es desasociada de la del padre, pasando a ser privada. CLONE_VM: la memoria virtual del proceso que realiza la llamada es desasociada del padre, dicho de otra forma, se asigna memoria para una nueva estructura vm y se copia la compartida en ella, pasando a ser privada. CLONE_FS: se copia la información del filesystem compartido en una nueva estructura privada al proceso. CLONE_NEWNS: la misma semántica pero para el espacio de nombres del sistema de archivos. Nueva primitiva de bloqueo “mutex”Hasta ahora existían tres métodos principales para garantizar la exclusión mutua en el acceso a regiones críticas, las operaciones atómicas, los spin locks y los semáforos (semaphores). Los dos últimos son conocidos comúnmente como locks. Recordamos que con los spin locks, cuando un proceso accede a la región critica adquiere el spin lock (adquiere el lock) hasta que sale del código de la región crítica. Si mientras un hilo de ejecución tiene adquirido el lock, algún otro hilo de ejecución intenta acceder a la misma región critica, intentará adquirir el lock, en cuyo caso no podrá y realizará un espera activa, es decir, intentará reiterativamente adquirir el lock (spin), no perderá la CPU, a menos que termine su timeslice. Con los semáforos, la espera por la adquisición de un lock ya adquirido se realizará de forma pasiva. Esto quiere decir que el proceso que intenta adquirir un lock (tipo semáforo) ya adquirido perderá la CPU, será colocado en una wait queue, quedando libre la CPU para planificar otro proceso. Cuando el lock sea liberado, uno de los procesos de la wait queue será despertado para que pueda adquirirlo. Con la salida de esta nueva versión del kernel, ha quedado definitivamente liberado una nueva primitiva para este tipo de bloqueos el “mutex”.Pueden ser considerados como una versión ligera de los semáforos. Su semántica es más simple que en los semáforos y aporta algunas ventajas: - La estructura que representa al mutex struct mutex es más pequeña que los semáforos en la mayoría de las arquitecturas. Por ejemplo en x86 “struct semaphore” ocupa 20 bytes y “struct mutex” 16 bytes. Una estructura más pequeña significa menos huella en RAM y una mejor utilización de la caché de la CPU. - Menos líneas de código en su implementación. Se obtienen los siguientes tamaños de la sección .text cuando se cambian todos los semáforos (con comportamiento similar a mutex) por los nuevos mutex: text data bss dec hex filenameSe ahorran 25051 bytes de código, un 0,76% de ahorro. - El subsistema mutex es ligeramente más rápido y tiene mejor escalabilidad en sistemas con gran carga de trabajo. Los cambios de contexto con mutex son más rápidos que con los semáforos. Se explica un resumen de su manejo a continuación. La estructura mutex es bastante simple: struct mutext {El campo count contiene el estado del mutex. Un valor de uno significa que el lock está disponible, un valor de cero significa que el lock está adquirido y un valor negativo indica que el lock está adquirido y procesos podrían estar esperando encolados. El API es bastante simple linux/mutex.h. Cada mutex debe ser inicializado en primera instancia, o bien en tiempo de compilación con:DEFINE_MUTEX(mutex_name);O en tiempo de ejecución con: mutex_init(struct mutex *lock);Una vez que el mutex ha sido inicializado puede ser adquirido el lock con: void mutex_lock(struct mutex *lock);Nuevo subsistema para temporizadores de alta resoluciónEl API del kernel proporciona un mecanismo flexible para la planificación de eventos en un determinado momento de tiempo futuro. Este mecanismo son los timers o temporizadores, son eficientes y fáciles de usar, pero siempre han tenido una limitación: la resolución del temporizador está limitada al período de la interrupción del reloj del sistema. Los timers actuales no pueden ser más precisos que 4ms. Esta precisión resulta suficiente para la mayoría de las aplicaciones, pero existen otras para las que resulta inaceptable, como los trabajos en tiempo real y algunas aplicaciones multimedia para el escritorio. Durante mucho tiempo los programadores han proporcionado parches para conseguir más alta resolución en los timers, pero hasta ahora no se ha incluido ninguno de ellos en la rama principal. Con esta nueva versión 2.6.16 se ha incluido un subsistema de temporizadores de alta resolución de Thomas Gleixner (high resolution timer subsystem) que ha sido llamado “hrtimers” (en las fases iniciales fue denominado “ktimers”). Después de fallidos intentos de dotar de alta precisión al sistema de temporizadores vigente se decidió reescribir un nuevo subsistema, que es el que se ha presentado en esta versión.El nuevo sistema gira en torno a un nuevo tipo de datos ktime_t, que encontramos en linux/ktime.h. Es usado para almacenar el tiempo en valores de nanosegundos. Su definición cambia según la arquitectura. En arquitecturas de 64 bits, el tipo primitivo de ktime_t es un valor entero de 64 bits que almacena nanosegundos. En arquitecturas de 32 bits, ktime_t es una estructura de dos campos, un valor de 32 bits que almacena segundos y otro que almacena nanosegundos. El orden de los campos depende de si la arquitectura subyacente es big-endian o no. Los dos valores serán tratados como un sólo valor de 64 bits.
Para la manipulación de este tipo de datos se proporciona un nutrido grupo de funciones y macros.El código actualmente está disponible para las plataformas: i386, x86_64, ARM, PPC, PPC64 y IA64. El código también ha sido integrado en el árbol -rt. Migración de páginas en NUMA (swap migration)Los sistemas NUMA (Non-Uniform Memory Access), están formados por grupos de nodos o procesadores, la memoria primaria que usan es de más rápido acceso según la cercanía al nodo que la necesita. Dicho de otra manera, siendo toda la memoria del sistema accesible por todos los procesadores, la memoria local (más cercana al procesador) es más rápida para trabajar que la memoria remota. El kernel Linux intenta que los procesares usen la memoria local e intenta en la medida de lo posible no desplazar procesos a otros nodos. Cuando los procesos inevitablemente deben ser movidos a otros nodos, la memoria del proceso que antes era local, pasa a ser remota. Lo ideal sería desplazar la memoria del proceso junto con el proceso. Este es el objetivo de esta nueva funcionalidad.Si bien han circulado bastantes parches relacionados, la solución incluida en 2.6.16 está basada en el parche de Christoph Lameter. Este parche no soluciona en su totalidad el problema, pero establece la suficiente infraestructura para la solución. En el parche se delega la decisión de migrar la memoria del proceso al espacio de usuario mediante la llamada al sistema: long migrate_pages(pid_t pid, unsigned long maxnode,La técnica inicial consiste en iterar sobre el espacio de memoria del proceso e intentar forzar que cada página que necesita ser migrada vaya al swap. Cuando el proceso obtenga un fallo de página, esta página requerida será enviada del swap a la memoria local del nuevo nodo. Esto llevará un tiempo evidentemente. Drop page-cache con /proc/sys/vm/drop_cachesAl escribir en esta entrada del procfs, el kernel volcará de memoria la caché de páginas (pagecache), dentries (entradas de directorio, componentes de un path) e inodos (representación de ficheros y directorios en memoria) limpios (en estado clean) dejando la memoria libre. Concretamente:echo 1 > /proc/sys/vm/drop_caches : Libera la pagecache.Esta funcionalidad ha sido implementada pensando en los test de benchmarking, para que resulten uniformes entre sistemas de archivos sin tener que reiniciar la máquina para alcanzar condiciones equivalentes. Puesto que la funcionalidad anterior se refiere a objetos limpios (clean), es responsabilidad del usuario volcar los objetos modificados (dirty, más actualizado en memoria que en el disco) mediante la llama al sistema “sync”. Nueva funcionalidad MADV_REMOVE para madvise()La llamada al sistema madvise(), advierte al kernel sobre cómo tratar la paginación en un rango de direcciones. Permite a las aplicaciones indicar al kernel cómo cual va a ser el uso de determinados VMAs para que este trate sus referencias de determinadas maneras. Algunos de estos comportamientos o advices son:MADV_NORMAL: el valor por defecto, no hace un tratamiento especial. MADV_RANDOM: se le comunica al kernel que las páginas van a ser referenciadas en orden aleatorio. MADV_SEQUENTIAL: se le comunica al kernel que las páginas se espera que se referencien en orden secuencial. Existen otras advices. Con esta nueva versión 2.6.16 del kernel se añade la advice MADV_REMOVE, que permite liberar un rango de páginas de un espacio de almacenamiento asociado: por ejemplo algunas aplicaciones (como los sistema de bases de datos) asignan grandes ficheros temporales tmpfs, cuando las aplicaciones o procesos terminan de usarlos, esa memoria puede ser liberada. La forma es usando esta nueva funcionalidad. Por tanto actualmente la funcionalidad trabaja con sistemas de archivos tmpfs y con shm. Opciones noatime/nodiratime por punto de montajeSe incluye un parche que cambia el código para usar las opciones de montaje noatime/nodirtime a nivel de objetos vfsmount (es decir, por cada instancia de montaje de un filesystem) en vez de a nivel de objeto super_block. Con la opción de montaje noatime, el kernel no actualiza el tiempo de acceso de todos los ficheros de este filesystem y con la opción nodiratime, hace lo mismo pero con el tiempo de acceso de los directorios. Con la activación de estas opciones en un filesystem el rendimiento del mismo aumenta significativamente, al reducirse las escrituras.Soporte EDAC: Error Detection And CorrectionSe añade a la rama principal del kernel el soporte para técnicas EDAC. Hasta la fecha el proyecto EDAC, inicialmente conocido como proyecto Bluesmoke (evolución del proyecto Linux-ECC), consistía en un conjunto de módulos para manejar problemas relacionados con el hardware. Con esta nueva versión del kernel podremos disponer de dicho soporte de serie. Actualmente su ámbito de acción se centra principalmente en el manejo de los errores de las memorias ECC y errores de paridad en los buses PCI. Más concretamente es soportado el hardware que detecta los siguientes errores:
Dispatch queue genérica para todos los I/O schedulersUn cambio importante se ha producido en el subsistema de entrada/salida a bloques de disco. Actualmente existen cuatro planificadores de disco disponibles, cada uno de los cuales realiza un ordenamiento de las peticiones de entrada/salida a disco, según su criterio óptimo, y las coloca en la dispatch queue. La dispatch queue será de donde el driver del dispositivo de bloques determinado recoja las peticiones. Cada planificador de entrada/salida posee una implementación de esa dispatch queue. En este parche, Tejun Heo, ha decidido que la proliferación de dispatch queues es un desperdicio de duplicación de código, así que ha implementado una dispatch queue genérica. La unificación de esta dispatch queue ayuda a asegurar que todos los planificadores de entrada/salida implementarán colas con la misma semántica. Y también simplifica a los planificadores liberándolos de la necesidad de tratar con peticiones no relacionadas con el filesystem (recordamos que pueden llegar peticiones específicas del hardware subyacente, como operaciones de diagnóstico en forma de petición de entrada/salida).Nueva política de planificación SCHED_BATCHComo sabemos las tareas que entran en el procesador inician su actividad con un valor de prioridad que es llamado el valor nice. Este valor tiene un rango de -20 a +19, siendo el -20 la más alta prioridad. Esta es la denominada static priority, cuyo valor el planificador de CPU no modifica, hasta que el usuario lo demanda. Por otro lado, el planificador mantiene un valor denominado dynamic priority, que es un valor calculado a partir de la static priority y el nivel de interactividad de la tarea. Básicamente consiste en aplicar un bonus o penalización en el rango de -5 a +5. Si la tarea es más interactiva se aplicará un valor negativo, si es consumidora de CPU se aplicará un valor positivo.Con la nueva política de planificación, un proceso etiquetado como SCHED_BATCH, indicará que usará intensivamente la CPU, y recibirá por ello un valor constante de penalización +5. No se recalculará el valor en función de la heurística de su tiempo de procesamiento. Por tanto a partir de esta versión del kernel 2.6.16 tendremos las siguientes políticas de planificación: SCHED_NORMAL, SCHED_FIFO, SCHED_RR y SCHED_BATCH.Soporte COW (copy-on-write) para mapeos hugetlbA partir de la serie 2.6 del kernel se dio la capacidad a los procesos de usar grandes páginas de memoria. Las modernas arquitecturas soportan tamaños de página de 4KB hasta 4MB como en i386, 4KB-8KB-64KB-256KB-1MB-4MB-16MB en ia64, 4KB y 16 MB como en PPC, etcétera. Los usuarios pueden hacer uso del soporte de esta característica a través de llamada al sistema mmap, o a través del estándar SYSv de memoria compartida con las llamadas al sistema shmget y shmat.La system call mmap mapea en memoria ficheros, permitiendo mapear grandes ficheros en páginas gracias a la característica anterior. Cuando se invoca esta llamada al sistema se debe indicar uno de los siguientes flags: MAP_FIXED, MAP_SHARED o MAP_PRIVATE. El primero indica al la syscall que si no puede mapear el fichero en la ubicación especificada devuelva un error. El siguiente indica que el objeto mapeado en memoria, también conocido como VMA, puede ser compartido con otros procesos (como las librerías compartidas) y el último indica que es un VMA privado con la característica copy-on-write (si el VMA está en memoria, sólo se copia para uso privado si se produce una escritura en él). Con este parche presentado en 2.6.16 se da soporte al flag MAP_PRIVATE en mmap, para grandes páginas. Con ello se permite que aplicaciones de espacio usuario puedan usar hugepages sin cambios en sus funciones de librería, como malloc(), la propia mmap(), etc. Añadido el SLOB allocator de Linux-TinyDel proyecto Linux-Tiny de Matt Mackall, la nueva versión 2.6.16 del kernel Linux incorpora el SLOB allocator. El SLOB (simple list of blocks) es un sustituto del tradicional SLAB allocator o layer. El SLOB está diseñado sobre una implementación tradicional de K&R/UNIX allocator, pensado para una minimización de espacio en memoria. Emula la habitual SLAB layer y la función kmalloc. La desventaja es que escala con mayor dificultad que SLAB y sufre de fragmentación, por tanto es indicado para sistema empotrados cuyo objetivo sea la minimización de memoria a extremo.Soporte de core dumps ELF configurableEn esta versión es posible desactivar el soporte de volcado de la imagen del proceso al producirse un core. Esto ahorra unos 5KB de tamaño de la imagen final. Esta implementación también es heredada del proyecto Linux-Tiny de Matt Mackall.Abandono definitivo del soporte GCC 2.95.xLa mínima versión de compilador permitida para compilar las fuentes es a partir de ahora la versión GCC 3.2. La elmininación del soporte a la serie de compiladores gcc-2.95.x ha tenido bastante controversia, pero al final por bastantes motivos, como la falta de características ya usadas en los nuevos drivers o la falta de soporte de las principales distribuciones Linux.Medida del impacto en memoria por cpusetLos cpuset son conjuntos de CPU y nodos de memoria asignables a conjuntos de tareas. Con este parche se facilita la medida de la presión que un conjunto de tareas asignadas a un cpuset puede estar provocando. Esta característica es ideal para herramientas de monitorización, que permitirán informes de mayor precisión en sistemas multiprocesador o arquitecturas NUMA.OCFS2: Oracle Cluster File System versión 2Se incorpora en la rama principal esta nueva extensión del Oracle Cluster File System para Linux, haciendo dicho filesystem compatible con POSIX. Se trata un sistema de archivos de propósito general que puede ser usado para compartir instalaciones Oracle, haciendo la administración de las instalaciones Oracle Real Application Cluster (RAC) mucho más fácil.Soporte TIPC: Transparent Inter Process CommunicationSoporte de este protocolo especialmente diseñado para la comunicación entre procesos dentro de un cluster. Ha formado parte de los productos de Ericsson durante muchos años fue portado portado a Linux y ahora ha sido incluido en la rama principal.printer-friendly version | login to post comments
|