Es.KernelKewbies.org


 

> Parches
> Estado actual del kernel
> Encargados del Kernel
> Registros IRC
> Registros de cambios
> Vendedores del kernel
> Libros recomendados
> Documentación
> Proyectos para el kernel
> Enlaces externos
> Lista de correo
> KernelNewbies-es Wiki
> Scripts utiles











 
  

Respuestas a preguntas frecuentes



Qué hay acerca de la serie de parches ac (Alan Cox) ?

  • Cuál es la diferencia con los kernel de Linus?
    Los kernel de Alan pueden parecer una prueba de cama para los kernel de Linus. Mientras Linus es muy conservativo y solo aplica parches obios y bien probados al kernel 2.4, Alan mantiene una serie de parches para el kernel que contienen nuevos conceptos, más y/o nuevos drivers, y parches más intrusivos. Si los parches demuestran ser estables, Alan los presenta a Linus para incluirlos en el kernel oficial. (Notese que actualmente el árbol -ac esta esencialmente en el limbo, conteniendo parches que necesitan ser adelantados por Marcelo para el 2.4. No hay árbol -ac para el 2.5)

    Solo la serie -ac contiene todas las correciones propuestas en la lista(s) de correo del kernel.

    Con el estado actual del árbol de Linus, se recomienda el uso de la series -ac.

  • Dónde los consigo ?
    Ve a ftp://ftp.kernel.org/pub/linux/kernel/people/alan/ donde "xx" es tu código de pais , e.j. "uk"
  • Cómo los aplico ?
    Ejemplo de como parchar del 2.4.2 -> 2.4.2-ac20. (Asumiendo que linux-2.4.2.tar.bz2 y patch-2.4.2-ac20.bz2 ambos han sido descargados del mismo directorio.
    bzip2 -dc linux.2.4.2.tar.bz2 | tar xvf -

    cd linux

    bzip2 -dc ../patch-2.4.2-ac20.bz2 | patch -p1

  • He descargado los archivos .gz en vez de los .bz2
    Mismo proceso, solo que se usa diferente programa para descomprimir.
    gzip -dc linux.2.4.2.tar.gz | tar xvf -

    cd linux

    gzip -dc ../patch-2.4.2-ac20.gz | patch -p1

  • Pero ya he aplicado un parche ac !
    Entonces reversalo :

    bzip2 -dc patch-2.4.2-ac19.bz2 | patch -p1 -R
    bzip2 -dc patch-2.4.2-ac20.bz2 | patch -p1

  • Por qué no puede haber "diferencias incrementales" entre las correcciones ac ?
    Si estas interesado, estan en http://www.bzimage.org/ o ftp://sunsite.icm.edu.pl/pub/Linux/kernel/incr/2.4






Qué es una etiqueta asmlinkage ?


La etiqueta asmlinkage es otra cosa que debemos observar acerca de esta simple función. Es como un #define para algunos gcc magic la cual le dice al compilador que la función no debe esperar encontrar alguno de estos argumentos en los registros (una optimización común), pero solo en la pila (stack) (stack) de la CPU. Rellama a nuestra previa asercion que system_call consume, este es el primer argumento, el número de llamada de sistema, y permite hasta cuatro argumentos más, que son pasados a lo largo de la verdadera llamada de sistema. system_call archiva este proceso simplemente dejando estos otros argumentos (los cuales fueron pasados a este como registros) en la pila (stack). Todas las llamadas de sistema son marcadas con la etiqueta asmlinkage, por eso todas ellas buscan argumentos en la pila (stack). Por supuesto, en el caso de las sys_ni_syscall, no son la excepción por que sys_ni_syscall no toma ningun argumento , pero es un número para la mayoría de otras llamadas del sistema. Y por eso veras etiquetas asmlinkage en frente de muchas otras funciones.





-

 Cómo comienzo ?


Una pregunta común hecha por un novato es "He descomprimido este enorme tarball, y quiero usarlo, pero no se donde comenzar!"

Puede parecer intimidatorio para ser confrontado con una gran cantidad de código fuente, pero ten en cuenta, que hay pocos hackers del kernel que entienden cada área del árbol del kernel.

Las personas se especializan. Si estas interesado en TCP/IP, no necesitaras leer sobre código de sistema de archivos. Piensa en que es lo quieres profundizar, y enfocate hacia ello.

Linux es un kernel de calidad profesional. Esto hace dificil que este parezca un "proyecto de estudiante" con el cual puedes aprender: las caracteristicas usuales ya estan implentadas, y aun nivel en el cual se requiere un buen nivel de entendimiento antes que puedar hacer hacking en el. Sin embargo, hay muchas cosas practicas y utiles que puedes hacer hasta que hayas aprendido lo suficiente para verdaderamente Comenzar en el hacking :

Pruebas y anotaciones
El nuevo código esta en constante evolución, pruebalo. Seguramente te daras cuenta que hay algunos comportamientos extraños: Aqui esta tu impetu para entender the donde proviene ese comportamiento. Perfila cosas y sigueles el rastro (ej. LTT), mira si puedes trabajar en lo que probablemente esta causando problemas. Aprenderas de ese código por accidente. Consigue los parches propuestos en las listas de correo del linux kernel y arboles como los -mjc. Consigue y entiende que hace un parche en particular, y como lo hace.
Documentación
Suena aburrido ? Talvez, le estes haciendo un favor a todos, no seria solo para ti. Esfuerzate para explicar las cosas de forma logica para tu entendimiento. La documentacion sobre los comportamientos del linux kernel, requiere que entiendas el código. Lo encontraras facil de leer si estas concentrado en responder una pregunta especifica. Escribe articulos para kernelnewbies y hazlos revisar en el canal IRC. Identifica irregularidades en las paginas-man (manual), y corrigelas. Añade los documentos a las fuentes del kernel.
Kernel janitors
Kernel janitors es un proyecto para corregir las APIs del kernel, en desuso, como mutación de código. Este es un interesante proyecto. Una charla educativa sobre el, puede leerse aquí aquí.








Cómo compilo un kernel ?


(Estas instrucciones suponen que estamos instalando la versión 2.4.0 del kernel, reemplaza todas las instancias, con la versión de kernel que vas a compilar. Estas instrucciones son también especificamente x86; la construcción para otras arquitecturas puede diferir.

  • Descarga el tarball de ftp.XX.kernel.org donde XX es el código de tu pais. si no hay algún mirror para tu pais, escoge el más cercano.
  • Descomprime el tarball en tu directorio /usr/src
       bzip2 -dc linux-2.4.0.tar.bz2 | tar xvf -

    (Reemplaza bzip2 por gzip si has descargado el .gz)
  • Cambiate al directorio linux. Ahora necesitas configurar el kernel para seleccionar las caracteristicas que quieres/necesitas. Hay varias formas de hacerlo..
       
    	a. make config
    preguntas tipo línea de comando.
    b. make oldconfig
    (Útil solo si mantienes el .config de una
    compilación previa de otro kernel)
    c. make menuconfig
    (configuración basada en ncurses)
    d. make gconfig
    (configuración gráfica GTK basada en X-Windows)
    e. make xconfig
    (configuración gráfica QT basada en X-Windows)
  • Ahora podemos compilar el kernel, pero primero debemos compilar las dependencias.
       make dep 
    make bzImage
  • Espera!, cuando esto haya finalizado, compila alguna parte que talvez hayas seleccionado para ser modular.
       make modules

  • Para la actual serie estable del linux kernel 2.6.x estos son los pasos
       make
       make modules
    notese que ya no es necesario hacer 'make dep' en los kernels 2.6.x
  • Cambia de usuario normal a root para poder instalar el kernel y los modulos. Todo antes de este punto puede y debe ser realizado como usuario normal, no hay necesidad de ser root para compilar el kernel. Actualmente es una muy mala idea hacer todo como root porque el root es demasiado poderoso, un simple error es capaz de arruinar tu sistema por completo.
  • Instala los modulos.
       make modules_install
  • Instala el nuevo kernel..
       cp arch/i386/boot/bzImage /boot/vmlinuz-2.4.0
    cp System.map /boot/System.map-2.4.0
  • Edita /etc/lilo.conf, y añade estas lineas...
       image = /boot/vmlinuz-2.4.0
    label = 2.4.0
    También copia aquí la línea root=/dev/???.

  • Ejecuta /sbin/lilo, reinicia, y disfruta. si tienes problemas con modversions (simbolos terminados en _Rxxxxxxxx), echa un vistazo a esta pregunta en las preguntas frecuentes de la lista de correo del linux kernel, para resolver el problema.
Aún no lo resuelves? Lee un tutorial más profundo

En SPARC, debes seguir los siguientes pasos
  • NOTA: para soporte a 64 bits se recomienda usar versiones > 3.1 del compilador gcc
  • Descomprime el tarball que has descargado de kernel.org
    tar xjvf linux-2.4.xx.tar.bz2
    o si descargaste el tarball comprimido con gzip, es lo mismo solo que haces esto
    tar xzvf linux-2.4.xx.tar.gz
  • Sigues la misma parte de configuración que en x86
  • Despues que hayas configurado las opciones de tu kernel, construye la imagen de arranque haz:
    make vmlinux
  • Ahora si construye e instala los modulos, tal y como se hace en x86:
    make modules
    A continuación:
    make modules_install
  • Instala el nuevo kernel
    cp vmlinux /boot/nuevo-kernel
    A continuación instala System.map
    cp System.map /boot/System.map-nuevo-kernel
  • opcional, pero recomendado, comprimir la imagen de arranque, si tienes una máquina un poco ya antigua, ej sun ultra enterprise 2, puede que tengas problemas para arrancar si no comprimes la imagen, en las maquinas Sun modernas es posible que no haya necesidad de hacerlo
    gzip /boot/nuevo-kernel
  • Edita el archivo /etc/silo.conf y agrega las siguientes lineas
    image=/boot/kernel.gz
    label=nuevokernel
    root=/dev/xxx
    - no olvides cambiar la linea root=/dev/xxx??, ejemplo root=/dev/sda5
    - no necesitas ejecutar /sbin/silo ya que el archivo de configuración se analiza al arranque, pero si quieres asegurarte de que no hay errores en el archivo /etc/silo.conf haz:
    /sbin/silo
    entonces te debe aparecer algo como esto:
    /etc/silo.conf seems to be correct
    eso significa que archivo de configuración parece tener correcta la sintaxis, he aquí un archivo de configuración ejemplo de /etc/silo.conf
      timeout=50
      partition=5
      root=/dev/sda5
      read-only
      image=/boot/vmlinux
        label=linux
      image=/boot/vmlinux.viejo
        label=viejo
      
  • Reinicia y listo!
  • Para mayor información visita ultralinux.org





Quienes son ... los maestros ?

Linus Torvalds.

Por favor, sea serio...

Alan Cox.

Alan nos visita de vez en cuando.



 Cómo aplico un parche ?


La respuesta, depende de como fue creado el parche especificamente desde que directorio fue aplicado. De forma general, los parches son creados desde la raiz del árbol (/usr/src/linux), y las siguientes instrucciones así lo suponen.

Por ejemplo consideremos que, has desempaquetado un tarball de Linux 2.4.0, y quieres aplicar un parche de Linus patch-2.4.1.bz2, el cual esta ubicado en /usr/src. Haz lo siguiente :

	cd /usr/src/linux
bzip2 -dc /usr/src/patch-2.4.1.bz2 | patch -p1 --dry-run
Usamos la opcion --dry-run para VERIFICAR que el parche se aplicara correctamente. Esto puede ser un salvadidas a veces puede ser un verdadero dolor de cabeza volver a un parche parcialmente aplicado. La opcion -p1 nos muestra parte de las diferencias en los nombres de las rutas para cada archivo reemplazado (mira la página manualpatch(1) para más detalles). Ahora que has verificado que se aplicara correctamente, ejecuta :
	bzip2 -dc /usr/src/patch-2.4.1.bz2 | patch -p1
para aplicarlo. Y listo !. Luego de esto se procede a compilar el kernel para poder usar las caracteristicas que brinde el parche
Esto es actualmente con los parches estandar simples de Linus, o también puedes usar el script linux/scripts/patch-kernel para que automaticamente aplique los parches por ti.

La situación con los otros parches no siempre es tan simple. Por ejemplo, los pre parches de Linus (se encuentran en pub/linux/kernel/testing) no son incrementales. Por eso es que pre10.bz2 debe ser aplicado en encima del tarball del previo lanzamiento completo del kernel. Ej, patch-2.4.8-pre2 va encima de un tarball 2.4.7 desempaquetado, *NO* encima de un kernel parchado 2.4.8-pre1. Si tienes un kernel 2.4.8-pre1, puedes volverlo a 2.4.7 a través de la siguiente sección (abajo) 'Reversando un parche'.

Los parches ac de Alan Cox (pub/linux/kernel/people/alan/) siguen el mismo metodo, a menos de que consigas los parches incrementales en bzimage.org.

Ocasionalmente querras probar un parche de la lista de correo del linux kernel o similares. Generalmente van a ser incrementales, opuestos a dicha versión (entonces, digamos que, 2.4.0-test1-ac22-hosedmm.diff debería ser aplicado opuesto a 2.4.0-test1-ac22), y relativo al root. Puedes necesitar jugar con la opcion -p.

A continuacion mostraremos un ejemplo de como aplicar un parche alan cox, bueno supongamos que patch-2.4.22-rc.bz2 y patch-2.4.22-rc2-ac1.bz2 han sido descargados del mismo sitio, a /usr/src/ entonces :

1. cd /usr/src/linux

2. Verificamos que el primer parche se aplicaria correctamente

bzip2 -dc ../patch-2.4.22-rc2.bz2 | patch -p1 --dry-run

Si el parche se aplicaria correctamente se veria algo como esto:

patching file arch/alpha/kernel/entry.S
patching file arch/alpha/kernel/process.c
patching file arch/alpha/kernel/smp.c
patching file arch/alpha/kernel/srmcons.c
patching file arch/alpha/mm/fault.c
patching file arch/arm/config.in
patching file arch/arm/mm/fault-common.c
patching file arch/cris/drivers/serial.c
patching file arch/i386/boot/setup.S
patching file arch/i386/config.in
patching file arch/i386/defconfig
patching file arch/i386/kernel/dmi_scan.c

y así sucesivamente ....

ahora que sabemos que el parche se aplicara adecuadamente, entonces pasamos a ejecutar la anterior línea de comando sin el parametro --dry-run
siguiente paso, una vez que se haya aplicado exitosamente el patch-2.4.22-rc2.bz2 procedemos a aplicar el segundo parche o sea patch-2.4.22-rc2-ac1.bz2 (el cual ira encima del patch-2.4.22-rc2.bz2),
NOTA : el orden en el que se aplican los parches es vital, por que de lo contrario el comando patch te sacara error. Entonces el aplicar el siguiente parche sigue el mismo procedimiento de arriba (se recomienda ejecutar el comando patch, con la opcion --dry-run para hacer una prueba en seco).
Una vez que los dos parches se han alplicado correctamente, se procede a compilar el kernel
Al hacer este proceso de parchado de un kernel, se puede obtener un error como el siguiente:

can't find file to patch at input line 4 Perhaps you used the wrong -p or --strip option? The text leading up to this was: -------------------------- |diff -u --new-file --exclude-from /usr/src/exclude --recursive linux.22-rc2/arch/alpha/ kernel/ entry.S linux.22-rc2-ac1/arch/alpha/kernel/entry.S |--- linux.22-rc2/arch/alpha/kernel/entry.S 2003-08-09 16:00:36.000000000 +0100 |+++ linux.22-rc2-ac1/arch/alpha/kernel/entry.S 2003-06-29 16:10:35.000000000 +0100 --------------------------
File to patch:

esto significa que debes corregir la opcion -p en el comando patch.

Reversando un parche

Haz aplicado muchos parches , y ahora quieres removerlos. Simplemente usa la opcion -R en comando patch, con el mismo archivo de parche, para reversarlo (nota, la página manual patch(1) es menos clara en esto).









 A Quién puedo encontrar en #kernelnewbies ?





Nombre Real Nick Responsabilidad en el kernel
Anton Altaparmakov AntonA ntfs
Arjan van de Ven arjan kHTTPd, Powertweak
Andre Hedrick ata IDE guru
Jens Axboe axboe CDROM/DVD layer
Ralf Baechle Bacchus Linux-MIPS
Ben LaHaise bcrl Administración de Memoria
Dave Jones davej encargado del árbol 2.5-dj., Powertweak, hacks aleatorios
Erik Mouw erikm ARM Linux, SA1100-Linux
f00f f00f Larting, jumping, y logging
Greg Kroah gregkh USB
Christoph Hellwig hch Sistemas de archivos, kbuild, kernel cleanup
Jeff Dike jdike User Mode Linux
Jeff Garzik jgarzik Drivers para trabajo en red, PCI, kernel cleanup
lxrbot lxrbot El canal oracle. Preguntale por definiciones y usos en las fuentes del kernel, or query its factoid database.
Thiago Rondon maluco Hacking aleatorio
Marcelo W. Tosatti marcelo Encargado 2.4
Michael J. Cohen mjc Guadian del árbol de kernel -mjc
John Levon movement oprofile, random minor hacking
Fabio O. Leite olive drbd, Alta Disponibilidad, heartbeat
Daniel Phillips phillips Sistema de archivos TUX2, implementación ext2, administración de memoria hacking
Juan Quintela quintela Administración de memoria
Rik van Riel riel Administración de memoria
Russell King rmk ARM Linux
Tigran Aivazian tigran Hacking aleatorio
Momchil Velikov velco VM hacker etc.
Alexander Viro viro guru del VFS
William Lee Irwin wli Hacking VM, bootmem, más

Por qué tantos #define en el kernel que usan do { ... } while(0)?


Hay un par de razones:

  • (Dave Miller dice) Declaraciones vacias generan un warning del compilador por eso es que ves #define FOO do { } while(0).
  • (Dave Miller dice) Esto te da un bloque basico en el cual se declaran variables locales.
  • (Ben Collins dice) Esto te permite usar macros más complejos en código condicional. Imagina un macro de muchas lineas de código como:
    #define FOO(x) \
            printf("arg es %s\n", x); \
            haz_algo_util(x);
    
    Ahora imagina usarlo así:
            if (blah == 2)
                    FOO(blah);
    Esto se interpretaria como:
            if (blah == 2)
                    printf("arg es %s\n", blah);
                    haz_algo_util(blah);;
    
    
    Como puedes ver, el if entoces solo reconce el printf(), y el haz_algo_util() en la llamada es incondicional (no con el condicional if), como lo querias. Entonces, usando un bloque do{...}while(0), conseguirias esto:
            if (blah == 2)
                    do {
                            printf("arg es %s\n", blah);
                            haz_algo_util(blah);
                    } while (0);
    
    Que es exactamente lo que querias.
  • (Per Persson dice) Como Miller y Davis ambos dicen, quieres una declaración de bloque entonces puedes tener muchas lineas de código y declarar variables locales. Pero entonces lo natural seria solo para ejemplo:
      #define exch(x,y) { int tmp; tmp=x; x=y; y=tmp; }
    
    
    Sin embargo esto no funcióna en algunos casos. El siguiente código significa una declaración ifcon dos bandas:
      if(x>y)
        exch(x,y);          // Rama 1
      else
        haz_algo();     // Rama 2
    
    Pero esto se interpretaria como una declaración if con solo una rama:
      if(x>y) {                     // declaración if con bandas sencilla!!!
        int tmp;            // La única banda consiste
        tmp = x;            // en el bloque
        x = y;
        y = tmp;
      }
      ;                             // declaración vacía
      else                  // ERROR!!! "error de analisis antes de else"
        haz_algo();
    
    El problema es el punto y coma (;) que esta directamente despues del bloque.

    La solución para esto es el sandwich del entre el bloque do y while(0). Entonces tenemos una declaración de línea sencilla con las capacidades de un bloque, pero no es considerada, como declaración de bloque por el compilador.

    Nuestra declaración if se convierte en :
      if(x>y)
        do {
          int tmp;
          tmp = x;
          x = y;
          y = tmp;
        } while(0);
      else
        haz_algo();
    
    







Cómo trabaja get_current() ?


static inline struct task_struct * get_current(void)
{
        struct task_struct *current;
        __asm__("andl %%esp,%0; ":"=r" (current) : "0" (~8191UL));
        return current;
}

get_current() es una rutina para conseguir acceso al task_struct de la actual tarea en ejecución. Esta presenta las usuales confusas caraterísticas del gcc inline assembly para hacer eso, algo como lo siguiente :

| __asm__(

Esto significa que una parte de la inline assembly que el compilador debe insertar en la salida de este código. El __asm__ es el mismo asm, pero este no puede ser desactivado por banderas de línea de comando.

| "andl %%esp,%0

"%%" es un macro que expande a "%".
"%0" es un macro que expande a la primera especificacion de entrada/salida.

Por eso en este caso, toma el puntero a la pila (stack) (registro %esp) y ANDs it dentro del registro que contiene 0xFFFFE000, dejando el resultado en el registro.

Basicamente, la pila (stack) de la tarea task_struct y una pila (stack) de tarea del kernel ocupa un bloque de 8KB, el cual es un bloque de 8KB alineado, con task_struct al comienzo y con el incremento de la pila (stack) desde el fin hacia atras. Por eso puedes encontrar task_struct limpiando en el fondo los 13 bits del apuntador al valor de la pila (stack).

| ; "

El punto y coma puede usarse para separar declaraciones assembly, tal como lo hace el caracter sequencia escape de nueva línea("\n").

| :"=r" (current)

Esto especifica una salida constante (todo esto ocurre despues de los primeros dos puntos, pero antes de los segundos). El '=' también especifica que esta es una salida. La 'r' que un registro de proposito general debera ser ubicado tal como esa instrucción puede ubicar la salida del valor dentro de esta. El bit dentro de las comillas simples - 'current' - es la destinacion encargada del valor de salida (normalmente una variable local) una vez es retornado a la parte C.

| : "0" (~8191UL));

Esto especifica una entrada constante (todo esto ocurre despues de los segundos dos puntos, pero antes de los terceros). El '0' referencia otra constante (en este caso, la primera salida constante), diciendole que el mismo registro o locacion de memoria debería usarse para ambos. El '~8191UL' dentro de las comillas simples es una constante que debería se cargada dentro del registro ubicado para el valor de salida antes de usar las instrucciones dentro del bloque asm.

Mira también las paginas de información de gcc, Tema "Extensiones C", subtema "Asm Extendido".

(Cortesia en su mayoría de David Howells de Redhat).



Cómo compilo un módulo ?


Los modulos para el kernel deben construirse de forma segura para que se compilen exitosamente en el kernel.
La línea de compilació&;n para la mayoría de modulos debería verse algo así :

gcc -o mimod.o -Wall -W -O2 -DMODULE -D__KERNEL__ -I/lib/modules/`uname -r`/build/include -c mi_mod.c

Debes usar la versión de gcc con la cual hayas compilado el kernel.
Debes especificar -O2 para hacer inline el código necesario.
Debes estar seguro de compilarlo opuesto las verdaderas cabeceras del kernel opuesto que estas compilando. Usando (por defecto) /usr/include/linux y amigos NO es suficiente. El ejemplo de abajo asume que estas construyendolo opuesto al kernel en ejecución, si no altera el parche con la opcion incluir -I.

MODVERSIONS

Modversions es el sistema de versiones para los simbolos exportados del kernel. Para compilarlo opuesto :
  • Debes añdir -DMODVERSIONS a la línea de compilación
  • El primer include debe ser
  • Si estas compilando un módulo con varios archivos fuente, debes debes añadir #define __NO_VERSION__ en todos pero, solo en uno de los archivos fuente .c. Notese que esto no es necesario con versiones recientes del kernel.
  • No debes incluir modversions.h directamente si tu módulo esta incluido en las fuentes del kernel. Si lo estas construyendo externamente, incluye el modversions.h correcto solo cuando las versiones de los modulos estan habilitadas (esto es mejor que añadirlos a las lineas de compilación como lo hace el kernel).

Por favor, también lee http://www.tux.org/lkml/, especialmente preguntas 8-7 y 8-8

Empaquetamiento externo

Si distribuyes tu módulo como un paquete separado, es mejor incluir algún autoconf setup para deteccion del kernel opuesto para compilar (por defecto a la ruta mensionada /lib/modules/... ). Una vez que tu script configure, ha encontrado el kernel, puede incluir Rules.make para usar las reglas de banderas correctas para el compilador etc. (esto es especialmente para banderas específicas de cada arquitectura). El módulo CIPE, por ejemplo, hace esto (vease parches).

La forma adecuada de compilar modulos

La forma confiable y enfocada a largo plazo de compilar modulos es dejar que el sistema de compilación del kernel haga el trabajo duro por ti. Usa autoconf o un mecanismo similar para localizar el árbol de código fuente del kernel (por defecto en la ruta siguiente a /lib/ modules/). Lee Documentation/kbuild, para ver como debería verse tu Makefile, para que el módulo se compile por sí mismo, y entonces cuadra una llamada desde el directorio base del kernel, es necesario especificar SUBDIRS. Por ejemplo, si tu Makefile generado esta en /home/usuario/src/mimodulo-0.1/módulo/, y el código fuente del árbol de kernel de los usuarios esta en /usr/src/linux-2.5/, entonces el fragmento de Makefile podria verse algo así:

kernel_module:
   $(MAKE) -C /usr/src/linux-2.5 SUBDIRS=/home/usuario/src/mimodulo-0.1/módulo/ modules

Esto establecera correctamente todas las banderas y tendra vigencia en el futuro usando la maquinaria de compilación del kernel por si mismo para generar el módulo.
Puedes encontrar un ejemplo simple para los kernels 2.6 aquí: sillymod.tar.gz, se compila de la forma estandar, "./configure, make, make install".







Qué significa un lsmod con cuenta -1 ?


Esto significa que el módulo ha declarado la función ->can_unload().

Los modulos normales se referencian vía cuenta. MOD_INC_USE_COUNT y amigos. Modulos con la función can_unload(), sin embargo, han decidido administrarse con el uso del módulo vía función, la cual retorna -EBUSY cuando el módulo no es descargable.

Un valor de -1 significa que lsmod es incapaz de determinar la descargabilidad del módulo, y la única forma de hacerlo es tratar con rmmod.







Cuál es la diferencia entre extern y static inline ?


Permite a Linus explicar :

 - 
"static inline" s.pngica "Tenemos que tener la función, si la usas
   pero no la haces inline, entoces se hara una versión estática de esta unidad de
   compilación"

 - "extern inline" significa "Actualmente _tengo_ un externa para esta función,
   pero si quieres tenerla inline, aquí esta la versión-inline"

Pero también mira funciónes Inline en C.







Qué es System.map ?


System.map es un archivo (producido vía nm) el cual con tiene los nombres de los simbolos y las direcciones del kernel binario de linux, vmlinux.

Se usa principalmente en depuracion. Si aparece un mensaje "oops" en el kernel, la utilidad ksymoops puede ser usada para decodificar el mensaje en algo util para los desarrolladores. ksymoops hace uso de System.map para mapear valores de la PC hacia valores simbolicos. Notese que los kernel 2.5 continen un decodificador de "oops" llamado kksymoops, el cual no necesita System.map

Puedes recibir warnings de System.map si este esta desactualizado. Esto no afectara la normal ejecución pero es mejor mantener una copia en caso de si hay un bug el kernel / falla de hardware. Note que ps l usa System.map para determinar el campo WCHAN (puedes especificar un archivo mapa con la variable de entorno PS_SYSTEM_MAP). Las Utilidades buscan en una serie de lugares estandar para este archivo tales como /boot/System.map y /usr/src/linux/System.map







Qué pasa con los archivos de cabecera del kernel ?


En cualquier distribución, hay dos tipos de cabeceras del kernel :

Cabeceras de sistema del kernel

Actualmente estas cabeceras son usadas por el sistema. Estas son las cabeceras con las cuales se compila las utilidades de espacio de usuario. Deben estar instaladas para compilar programas de espacio de usuario.

Las cabeceras usualmente se encuentran en /usr/include/asm y en /usr/include/linux. Son copias nunca deberian modificarse (a menos que actualices una librería C). Esas cabeceras continenen código para compatibilidad etc. para permitirles ser usadas con una variedad de kernels en ejecución, y conceptualmente son parte del paquete glibc. Usualmente pueden ser encontradas en el paquete/RPM. kernel-headers o en libc6-dev

Cabeceras de fuente del kernel

Son parte del paquete de las fuentes del kernel. Estas nunca deben usarse para compilación de programas de espacio de usuario. Las viejas distribuciones usualmente hacian /usr/include/linux y /usr/include/asm vinculos simbolicos a las partes correctas del árbol fuente del kernel, instaladas en /usr/src/linux. Esto esta mal hecho - programas de espacio de usuario deben usar cabeceras, convenientemente modificadas.

Conversely, cuando se compila el kernel o modulos para este, estas cabeceras deben ser usadas. Esto es importante cuando se compila modulos empaquetados externamente - la compilación del módulo debería ir en el lugar correcto para las cabeceras (por e.j. añadiendo -I /lib/modules/`uname -r`/build/include).

Lee la explicación de Linus a esta situación.





Qué valor mayor/menor tiene XXX ?

Mira devices.txt.




Cuales son los multiples arboles de kernel ?


-ac
Encargado: Alan Cox
Parches pendientes para enviarlos a Marcelo (para la serie 2.4), extra adiciones, y correciones. etc.
-mm
Encargado: Andrew Morton
Elegantes nuevas caracteristicas y correciones enfocadas al hacking del subsistema VM.
-mjc
Encargado: Michael Cohen
Mas correcciones extra para la serie 2.4 del kernel, implementaciones VM etc. Usualmente contiene parches más experimentales aun no propiamente listos para el 2.4.
-aa
Encargado: Andrea Arcangeli
Actualizaciones para VM, multitud de correciones y varias implementaciones de Andrea.
-dj
Encargado: Dave Jones
Adelanta correciones del 2.4 para la serie 2.5 . (a slightly less bloody bleeding edge)
-ck
Encargado: Con Kolivas
Una serie de parches estables para el 2.4, enfocados al rendimiento del scheduler y la VM, con un optimización especifica del desktop, para mejorar la respuesta del sistema.

-osdl
Encargado: open source development labs
Para centros de datos o carrier grade linux, incluye especialmente optimizaciones para grandes maquinas y alto rendimiento en bases de datos.

-rmap
Encargado: Rik van Riel
rmap realiza en su mayoría un mapeo inverso de marcos de páginas a mapeos virtuales, con el propósito de hacer una VM más predecible, para liberarse de algunos de los peores casos de comportamiento de la VM y facilitar las cosas. Los mapeos inversos proveen una infraestructura para hacer lo más flexible posible la VM, lo cual significa que las estrategias en -rmap cambian a menudo.



Cómo intercepto llamadas de sistema ?


Puedes usar algo como el el kit de herramientas para trazado de Linux probablemente.

Hay también un horrible hack basado en la modificación de las entradas en la tabla de llamadas del sistema. Esto es altamente no recomendado, no es seguro contra la descarga del módulo, esto no es independiente de la arquitectura, y esto es incorreto de cualquier forma.

Habiendo dicho eso, esto parece tarea común para el aprendizaje del hacking en el kernel. Mira el módulo syscalltrack para algo de código que actualmente haga esto..

Basicamente cada valor apuntado en la tabla global sys_call_table es modificado para apuntar a una nueva dirección proporcionada por el módulo del kernel, de esta forma cuando el proceso hace la llamada de sistema, terminará la rutina. Puedes entonces llamar al antiguo valor guardado de la llamada de sistema para procesar el pedido y despues recolectar cualquier información que necesites.

Esto falla horriblemente para la llamada de sistema execve, y hay una muy buena razón para esto. Echemos un vistazo al prototipo de sys_execve() :

asmlinkage int sys_execve(struct pt_regs regs)

Notese que el argumento - no es un puntero ! Tu intento de intercerptar sys_execve no funcionara. Este argumento indica que los registros de los procesos han sido guardados en la pila (stack). El código dentro de sys_execve actualmente modifica esas locaciones de la pila (stack) para ubicarlas el valor del registro del PC al comienzo del nuevo ejecutable - Por eso debes permitir el acceso al código en punto original de la pila (stack) !

Por ejemplo el código que hace la modificación de los registros, mira start_thread() llamada desde load_elf_binary().

La forma más simple de get around este problema es llamando a do_execve() en vez del antiguo valor guardado en el punteo al valor sys_execve pointer value, duplicando el código del kernel sys_execve(). Suena feo ? Por favor no hagas esto en el código verdadero. Si quieres prover algún código en el módulo que el kernel necesite llamar, provee un hook en el código del kernel, como un parche, despues un módulo encima de este (un ejemplo de esto es sys_nfsservctl()).

Notese que Linus quito el exportado de sys_call_table en los kernel 2.5.







Puedo usar funciones de librería en el kernel ?


Librerias de sistema (tales como glibc, libreadline, libproplist, cualquiera que sea) que estan tipicamente disponible para los programadores de espacio de usuario, no lo estan para los programadores del kernel. Cuando un proceso esta siendo cargado, el cargador carga alguna librería dependiente en el espacio de dirección del proceso. Ninguno de estos mecanismos esta disponible para los programadores del kernel, olvidate del las librerías ISO C, las unicas cosas disponibles son las que ya estan implementadas (y exportadas) en el kernel y lo que tu puedas implementar.

Mira que es posible "convertir" librerías para trabajar en el kernel; sin embargo, no se acomodaran bien, el proceso es tedioso y esta sujeto a errores, y posiblemente haya problemas con la el manejo de la pila (stack) (el kernel esta limitado a una pequeña cantidad de espacio en pila (stack), mientras que los programas de usuario no tienen esa limitacion) causando corrupcion aleatoria de memoria.

Muchas de las funciónes usualmente más usadas ya han sido implememtadas en el kernel, a veces en las versiones "ligeras" las cuales no son tan completas como las demas. Debes estar seguro de filtrar las cabeceras para alguna función que puedas usar antes de escribir tus propias versiones de los scratch. Algunas de las más comunmente usadas estan en include/linux/string.h.

Cuando sientas la necesidad de usar una función de librería, deberias considerar su diseno, y preguntarte si puedes migrar todo o parte de ese código de espacio de usuario.






Hay algún buen IDE (Entorno de Desarrollo Integrado)?
Cómo manejo todo ese código?



Cuando trabajas con gran cantidad de código fuente, como lo es el kernel, seguramente te ayudara tener algunas herramientas de software parar entender como los programadores se acomodan a ambos. Quizas la herramienta más importante es un buen editor de text para el programador. Elecciones populares son emacs y cualquier clon de vi, tal como vim. Generalmente, los editores de texto escritos para programadores son programables y tienen caracteristicas como selección de sintaxis, despliege de texto, búsqueda de patrones y facil integración con herramientas de manejo de código, tales como make(1), cvs(1), reformateo de texto, búsqueda en paginas de manual y más.

La herramienta más popular es la que busca rapidamente, usos, definiciones y declaraciones de simbolos C. grep(1) esta casi siempre disponible, y la versión más poderosa, egrep(1), es muy util conocerla. Pero grep(1), requiere búsqueda de todos los archivos en todas las busquedas. Herramientas como cscope, freescope, etags, ctags, y idutils construyen bases de datos para la búsqueda de simbolos C. Cada una tiene su propia idiosincracia y caracteristicas. Algunas se integran mejor con el editor de tu preferencia. (busca especialmente plugins para la integración.)

cgvg es otra opcion, la cual no aparece como una base de datos para busquedas rapidas.