¡Esto es realmente tiempo real! el kernel compilado con el parche rt nos habilita muchas posibilidades pero no las activa, recién después de aplicar esta configuración no vamos a tener nunca pérdida de audio (xruns) y vamos a poder usar latencias muy bajas.
El paso final es establecer unas cuantas prioridades de tareas. El parche para tiempo real debería haber creado varias tareas IRQ, así como una tarea hrtimer. Pueden visualizarse con el comando:
# ps -e
nos muestra lo siguiente (solo copio las tareas que nos pueden llegar a interesar para audio ya que son muchas, para ahorrar espacio):
| PID | TTY | TIME | CMD |
| 1 | ? | 00:00:01 | init |
| 2 | ? | 00:00:00 | kthreadd |
| 3 | ? | 00:00:00 | migration/0 |
| 4 | ? | 00:00:00 | posixcputmr/0 |
| 6 | ? | 00:01:11 | sirq-timer/0 |
| 12 | ? | 00:00:00 | sirq-hrtimer/0 |
| 53 | ? | 00:00:00 | IRQ-9 |
| 295 | ? | 00:00:25 | IRQ-12 |
| 296 | ? | 00:00:00 | IRQ-1 |
| 303 | ? | 00:00:00 | IRQ-8 |
| 616 | ? | 00:00:00 | IRQ-16 |
| 628 | ? | 00:00:00 | IRQ-19 |
| 645 | ? | 00:00:00 | IRQ-18 |
| 665 | ? | 00:00:00 | IRQ-23 |
| 692 | ? | 00:00:00 | IRQ-6 |
| 752 | ? | 00:00:02 | IRQ-14 |
| 753 | ? | 00:00:05 | IRQ-15 |
| 1435 | ? | 00:00:00 | IRQ-7 |
| 1493 | ? | 00:01:14 | IRQ-17 |
| 1872 | ? | 00:00:08 | IRQ-20 |
| 2480 | ? | 00:00:00 | IRQ-4 |
| 2483 | ? | 00:00:00 | IRQ-3 |
Nos interesan las tareas: sirq-timer/0, sirq-hrtimer/0 y la IRQ de nuestra placa de sonido que tenemos que ubicar cual es (ya voy a explicar como ubicarla). En un sistema core dual debe haber dos de cada tarea, una por cada CPU. Yo no pude comprobarlo porque no tengo core dual.
Vamos a tomar nota del PID de cada una: 6 (sirq-timer) y 12 (sirq-hrtimer).
Luego vamos a buscar el pid de la tarea IRQ en la que reside la tarjeta de sonido.
Vemos la salida de:
# cat /proc/interrupts
debería revelar esto:
| CPU0 | |||
| 0: | 200 | IO-APIC-edge | timer |
| 1: | 14890 | IO-APIC-edge | i8042 |
| 3: | 2 | IO-APIC-edge | |
| 4: | 1 | IO-APIC-edge | |
| 6: | 7 | IO-APIC-edge | floppy |
| 7: | 0 | IO-APIC-edge | parport0 |
| 8: | 2 | IO-APIC-edge | rtc0 |
| 9: | 0 | IO-APIC-fasteoi | acpi |
| 12: | 529675 | IO-APIC-edge | i8042 |
| 14: | 88412 | IO-APIC-edge | ide0 |
|
15: |
587044 |
IO-APIC-edge |
ide1 |
|
16: |
0 |
IO-APIC-fasteoi |
uhci_hcd:usb1 |
|
17: |
1685387 |
IO-APIC-fasteoi |
ICE1712 |
|
18: |
0 |
IO-APIC-fasteoi |
uhci_hcd:usb3 |
|
19: |
0 |
IO-APIC-fasteoi |
uhci_hcd:usb2 |
|
20: |
19611 |
IO-APIC-fasteoi |
eth0 |
|
23: |
229710 |
IO-APIC-fasteoi |
ehci_hcd:usb4 |
|
NMI: |
0 |
Non-maskable interrupts |
|
|
LOC: |
7295599 |
Local timer interrupts |
|
|
RES: |
0 |
Rescheduling interrupts |
|
|
CAL: |
0 |
function call interrupts |
|
|
TLB: |
0 |
TLB shootdowns |
|
|
TRM: |
0 |
Thermal event interrupts |
|
|
SPU: |
0 |
Spurious interrupts |
|
|
ERR: |
0 |
|
|
|
MIS: |
0 |
|
Entonces según esta información:
17: 1660453 IO-APIC-fasteoi ICE1712
el IRQ-17 es donde está mi placa de sonido (en mi caso me doy cuenta porque ICE1712 es el chipset de las m-audio, que es mi placa)
Para obtener el PID, uso de nuevo el comando:
# ps -e
si se fijan al principio del documento (cuando mostre el resultado de #ps -e) era el PID 1493
Ahora vamos a utilizar el comando chrt para establecer prioridades real time. En Debian, este comando forma parte del paquete schedutils. No importa el orden en el que se establecen las prioridades.
Establecemos nuevas prioridades para cada tarea:
En mi caso: # chrt -f -p 99 6
# chrt -f -p 99 12
# chrt -f -p 99 1493
Esto debe establecer una prioridad de tiempo real a las tareas identificadas como 6, 12 y 1493. Una prioridad tan alta como 99 podría no ser en realidad necesaria e incluso un tanto insegura (para mi si es necesaria).
Hay que probar con valores (por lo menos de 50 a 99) hasta encontrar los adecuados.
Luego y usamos el comando:
# top
para ver si cambiaron las prioridades (antes ejecuté jackd para poner en uso la placa de sonido para que aparezca IRQ-17 entre los procesos) me devuelve:
| PID | USER | PR | NI | VIRT | RES | SHR | S | %CPU | %MEM | TIME+ | COMMAND |
| 2747 | gabriel | 20 | 0 | 22588 | 2052 | 1716 | S | 11.6 | 0.1 | 0:02.91 | jackd |
| 2718 | gabriel | 20 | 0 | 37700 | 13m | 9.9m | S | 11.3 | 0.9 | 0:09.77 | gnome-terminal |
| 2741 | gabriel | 20 | 0 | 44080 | 11m | 9.8m | S | 10.0 | 0.8 | 0:02.98 | qjackctl |
| 2577 | root | 20 | 0 | 97.8m | 11m | 4788 | S | 6.6 | 0.8 | 0:07.85 | Xorg |
| 1493 | root | RT | -5 | 0 | 0 | 0 | S | 3.3 | 0.0 | 0:01.19 | IRQ-17 |
| 2713 | gabriel | 20 | 0 | 30472 | 11m | 7524 | S | 1.7 | 0.7 | 0:01.77 | pcmanfm |
| 295 | root | -51 | -5 | 0 | 0 | 0 | S | 0.7 | 0.0 | 0:00.70 | IRQ-12 |
| 2711 | gabriel | 20 | 0 | 20560 | 10m | 7168 | S | 0.7 | 0.7 | 0:04.87 | lxpanel |
| 2739 | gabriel | 20 | 0 | 2428 | 1136 | 900 | R | 0.3 | 0.1 | 0:00.41 | top |
| 1 | root | 20 | 0 | 2132 | 748 | 652 | S | 0.0 | 0.0 | 0:01.38 | init |
| 2 | root | 15 | -5 | 0 | 0 | 0 | S | 0.0 | 0.0 | 0:00.00 | kthreadd |
| 3 | root | RT | -5 | 0 | 0 | 0 | S | 0.0 | 0.0 | 0:00.00 | migration/0 |
| 4 | root | RT | -5 | 0 | 0 | 0 | S | 0.0 | 0.0 | 0:00.00 | posixcputmr/0 |
| 5 | root | -51 | -5 | 0 | 0 | 0 | S | 0.0 | 0.0 | 0:00.00 | sirq-high/0 |
| 6 | root | RT | -5 | 0 | 0 | 0 | S | 0.0 | 0.0 | 0:00.33 | sirq-timer/0 |
| 7 | root | -51 | -5 | 0 | 0 | 0 | S | 0.0 | 0.0 | 0:00.00 | sirq-net-tx/0 |
| 8 | root | -51 | -5 | 0 | 0 | 0 | S | 0.0 | 0.0 | 0:00.00 | sirq-net-rx/0 |
en este caso no aparece la línea:
| 12 | root | RT | -5 | 0 | 0 | 0 | S | 0.0 | 0.0 | 0:00.01 | sirq-hrtimer/0 |
pero se debe a que top esta en movimiento todo el tiempo (pero les aseguro que está).
Como pueden ver en la sección PR se puede ver la prioridad RT a la que están corriendo las tareas sirq-timer/0, sirq-hrtimer/0 y IRQ-17.
En realidad todo lo que hicimos hasta ahora sirve para probar el funcionamiento de las prioridades. Estas prioridades serán restablecidas después de cada reinicio, así que deberá crearse un script de inicio sencillo, para recuperarlas.
Dado que los pids de sirq-timer/0 y sirq-hrtimer/0 no van a cambiar, pero el pid de la placa de sonido sí, vamos a usar “pgrep” para que busque la tarea IRQ-17, a continuación describo como tiene que ser el contenido del script y donde debemos copiarlo, (yo voy a usar el editor de textos nano pero ustedes pueden usar el que quieran) :
# nano realtime.sh
copiamos lo que sigue a continuación adentro:
#!/bin/bash
#el 99 es la prioridad y el 6 el pid del sirq-timer
chrt -f -p 99 6
#el 12 es el pid de sirq-hrtimer
chrt -f -p 99 12
#IRQ-17 es el IRQ de la placa de sonido
chrt -f -p 99 `pgrep IRQ-17`
presionamos ctrl-o para salvar y luego <enter>
Luego le damos permisos de ejecución con:
# chmod +x realtime.sh
Y lo copiamos a /etc/init.d :
# cp realtime.sh /etc/init.d/
Y creamos un enlace simbólico que copiamos a /etc/rc5.d ; /etc/rc4.d ; /etc/rc3.d y a /etc/rc2.d
# ln -s /etc/init.d/realtime.sh /etc/rc5.d/S99realtime
# cp /etc/rc5.d/S99realtime /etc/rc4.d/
# cp /etc/rc5.d/S99realtime /etc/rc3.d/
# cp /etc/rc5.d/S99realtime /etc/rc2.d/
Para comprobar que todo funciona una vez reiniciado el sistema usar el comando top de nuevo.
Nota sobre APIC: En placas bases con APIC y kernels donde APIC está habilitado, pueden tenerse dificultades al establecer prioridades en las IRQ. Simplemente iníciese la máquina con la opción noapic en grub para el kernel utilizado, y compruébese si desaparecen los problemas.
He realizado este artículo basándome en el de Florian Paul Schmidt (muy completo el que quiera lo puede buscar en la web) pero agregando todo lo que yo pude experimentar.
Espero que sirva.
