Cómo forzar que el kernel de Linux se "congele" (o casi se congele) durante unos cientos de milisegundos

Cómo forzar que el kernel de Linux se "congele" (o casi se congele) durante unos cientos de milisegundos

Estamos ejecutando un proceso en tiempo real en un kernel que no es en tiempo real (CentOS 6) y probablemente esto no vaya a cambiar.

Tenemos una aplicación de transmisión de video que requiere alrededor de 500 MB/s de tráfico PCIe desde una FPGA personalizada de forma continua durante 1,5 horas seguidas. La aplicación funciona bastante bien, la mayor parte del tiempo. Sin embargo, hemos tenido situaciones en las que parece que el kernel simplemente deja de responder al servicio de PCIe o solicitudes de memoria durante hasta 500 milisegundos a la vez. Esto parece suceder durante la E/S de un archivo en ráfagas desde otro subproceso. Me ha resultado imposible intentar replicar este problema simplemente realizando muchas E/S de archivos ficticios desde el espacio del usuario mientras se ejecuta la aplicación principal.

¿Hay alguna manera de forzar (simular) una "congelación" global del kernel de Linux (en particular, detener PCIe o todos los accesos a la memoria DDR3 o algo así) para que podamos reproducir este problema?

Hemos implementado un almacenamiento en búfer de hasta 10 milisegundos en este momento en la memoria interna FPGA, pero eso no es suficiente. Podemos almacenar en búfer FPGA DDR3 y luego volcarlo al host, pero necesitamos un método para probar esta nueva característica bajo presión.

No queremos que el kernel se congele o se bloquee permanentemente. Nos gustaría tener la posibilidad de establecer el intervalo de tiempo.

Estoy buscando algo como escribir valores mágicos /proc/sys/vmtemporalmente que hagan que el sistema prácticamente se arrastre y luego retroceder después de unos cientos de milisegundos, pero observar la cantidad de formas posibles de romperlo no es para un novato como yo (https://www.kernel.org/doc/Documentation/sysctl/vm.txt). ¿Quizás algo de numactlmagia?

Respuesta1

Una opción para hacer una prueba rápida podría ser usar un kernel habilitado para KGDB y detener el kernel manualmente y probar,ver este enlace.

Por otra parte, cosas que recuerdo que podrían provocar tus pausas:

  • cpufreq, cat /sys/devices/system/cpu/cpu0/cpufreq/cpuinfo_transition_latencyel valor está en ns (4000 en mi procesador AMD FX(tm)-8120 de ocho núcleos) no debería ser un problema, pero verifique
  • Estrangulamiento térmico ya sea de la propia CPU o del módulo regulador de voltaje.
  • NAPI y/o tráfico de red intenso
  • ASPM PCIe ( cat /sys/module/pcie_aspm/parameters/policy)
  • Contención en los buffers de su dispositivo de destino (disco duro, nic...)
  • Error en el firmware de algún dispositivo en el bus PCIe (aunque no lo estés usando), puedes probar a apagarlos con/sys/bus/pci/devices/$DEVICE/power/control

Respuesta2

¿Podemos tener más detalles sobre cómo se comunica su aplicación con la FPGA? ¿Es la aplicación la que lee el búfer de la FPGA o la FPGA que envía interrupciones al kernel (como las tarjetas de red)?

Espero que abra un bloque/carácter en/dev y luego se comunique con él. Esto significa que utiliza un controlador para realizar la comunicación entre la aplicación y el archivo /dev/XXX.

Me gustaría tener el resultado de : cat /proc/interrupts; lsmod;ls -al /dev/yourmod

Aquí están las ideas:

  • Si se trata de una interrupción, puede configurar el PIC de la CPU para deshabilitar la IRQ correspondiente y luego volver a habilitarla. Esto hará que se ignoren todas las solicitudes de la tarjeta (sin que la tarjeta se dé cuenta).
  • Si es como una lectura de búfer, puedes:
    • Coloque su aplicación en estado de suspensión, para que los datos de la FPGA no se lean y su búfer se llene, luego active su aplicación y continúe la lectura.
    • Utilice "crash" o "kgdb" para cambiar el valor de "lectura" a "noop" durante unos segundos, luego vuelva a configurarlo a la función predeterminada.

Proporcione toda la información que pueda resultarle útil.

Respuesta3

No estoy seguro si ayuda. Pero si puede escribir un módulo del kernel que llame a la suspendfunción del módulo del kernel de otro dispositivo, eso puede ser suficiente.

Cada dispositivo PCI se puede suspender según el archivo de encabezadohttp://www.cs.fsu.edu/~baker/devices/lxr/http/source/linux/include/linux/pci.h#L479

Por ejemplo, aquí está la función de suspensión de la NIC Intel e1000http://www.cs.fsu.edu/~baker/devices/lxr/http/source/linux/drivers/net/e1000e/netdev.c#L4643

Por lo que puedo recordar, esta función se usó principalmente cuando el sistema entra en hibernación, el controlador del dispositivo necesita guardar el estado de ejecución actual y apagarse.

Respuesta4

Creo que estás pensando en el sentido equivocado. Tu objetivo es claro.

La forma no es detener el resto de los procesos, sino dar a los procesos principales una prioridad de programación casi en tiempo real. Usarlindopara sus importantes procesos de espacio de usuario para eso.

El problema más difícil es el manejo de interrupciones PCIe, que reside en el espacio del kernel.

Dado que se trata de hardware, debería empezar a observar más de cerca el carril PCIe involucrado en su placa base y cómo está posiblemente conectado a un zócalo de CPU específico.

equilibrio irqnormalmente hace un buen trabajo aquí, pero puedes configurar su comportamiento para adaptarlo a tus necesidades.

información relacionada