Como forçar o kernel do Linux a “congelar” (ou quase congelar) por algumas centenas de milissegundos

Como forçar o kernel do Linux a “congelar” (ou quase congelar) por algumas centenas de milissegundos

Estamos executando um processo em tempo real em um kernel que não é em tempo real (CentOS 6) e isso provavelmente não vai mudar.

Temos um aplicativo de streaming de vídeo que requer cerca de 500 MB/s de tráfego PCIe de um FPGA personalizado continuamente por 1,5 horas por vez. O aplicativo funciona muito bem – na maioria das vezes. No entanto, tivemos situações em que parece que o kernel simplesmente para de responder ao serviço de PCIe ou solicitações de memória por até 500 milissegundos por vez. Isso parece acontecer durante a E/S de arquivo em rajadas de outro thread. Achei impossível tentar replicar esse problema apenas executando muitos arquivos IO fictícios do espaço do usuário enquanto o aplicativo principal está em execução.

Existe uma maneira de forçar (simular) um "congelamento" global do kernel Linux (em particular, interrompendo o PCIe ou todos os acessos à memória DDR3 ou algo parecido) para que possamos reproduzir este problema?

Temos buffer de até 10 milissegundos implementado agora na memória interna do FPGA, mas isso não é suficiente. Podemos armazenar em buffer no FPGA DDR3 e depois despejar no host, mas precisamos de um método para testar esse novo recurso sob pressão.

Não queremos que o kernel congele ou trave permanentemente. Gostaríamos de poder definir o intervalo de tempo.

Estou procurando algo como escrever valores mágicos /proc/sys/vmtemporariamente que faça o sistema praticamente rastejar e depois reverter depois de algumas centenas de milissegundos, mas olhar para o número de maneiras possíveis de quebrá-lo não é para um novato como eu (https://www.kernel.org/doc/Documentation/sysctl/vm.txt). Talvez um pouco de numactlmagia?

Responder1

Uma opção para fazer um teste rápido poderia ser usar um kernel habilitado para KGDB e parar o kernel manualmente e testar,veja este link.

Por outro lado, lembro-me de coisas que podem causar suas pausas:

  • cpufreq, cat /sys/devices/system/cpu/cpu0/cpufreq/cpuinfo_transition_latency, o valor está em ns (4000 no meu processador AMD FX(tm)-8120 Eight-Core) não deve ser um problema, mas verifique
  • Estrangulamento térmico da própria CPU ou do módulo regulador de tensão.
  • NAPI e/ou tráfego de rede pesado
  • ASPM PCIe ( cat /sys/module/pcie_aspm/parameters/policy)
  • Contenção nos buffers do seu dispositivo de destino (disco rígido, nic...)
  • Bug no firmware de algum dispositivo no barramento PCIe (mesmo que você não esteja usando), você pode tentar desligá-los com/sys/bus/pci/devices/$DEVICE/power/control

Responder2

Podemos ter mais detalhes sobre como sua aplicação está se comunicando com o FPGA? É o aplicativo que lê o buffer do FPGA ou o FPGA que envia interrupção ao kernel (como placas de rede)?

Espero que ele abra um bloco/char em/dev e depois se comunique com ele. Isso significa que ele usa um driver para fazer a comunicação entre a aplicação e o arquivo /dev/XXX.

Eu gostaria de ter a saída de : cat /proc/interrupts; lsmod;ls -al /dev/yourmod

Aqui estão as ideias:

  • Se for acionado por interrupção, você pode configurar o PIC da CPU para desabilitar o IRQ correspondente e reativá-lo. Isso fará com que todas as solicitações do cartão sejam ignoradas (sem que o cartão perceba).
  • se for como uma leitura de buffer, você pode:
    • Coloque seu aplicativo em estado de suspensão, para que os dados do FPGA não sejam lidos e seu buffer seja preenchido, então ative seu aplicativo e continue a leitura.
    • Use "crash" ou "kgdb" para alterar o valor "read" para "noop" por alguns segundos e, em seguida, defina-o novamente para a função padrão.

Forneça todas as informações que você possa achar úteis.

Responder3

Não tenho certeza se isso ajuda. Mas se você puder escrever um módulo do kernel que chame a suspendfunção do módulo do kernel de outro dispositivo, isso poderá servir.

Cada dispositivo PCI pode ser suspenso de acordo com o arquivo de cabeçalhohttp://www.cs.fsu.edu/~baker/devices/lxr/http/source/linux/include/linux/pci.h#L479

Por exemplo, aqui está a função de suspensão da NIC Intel e1000http://www.cs.fsu.edu/~baker/devices/lxr/http/source/linux/drivers/net/e1000e/netdev.c#L4643

Pelo que me lembro, esta função era usada principalmente quando o sistema entrava em hibernação, o driver do dispositivo precisava salvar o status de execução atual e desligar-se.

Responder4

Acho que você está pensando da maneira errada. Seu objetivo é claro.

O caminho não é parar o resto dos processos, mas dar aos seus processos principais prioridade de agendamento quase em tempo real. Usarlegalpara seus processos importantes do espaço do usuário para isso.

O problema mais difícil é o tratamento de interrupções PCIe, que reside no espaço do kernel.

Como o hardware está envolvido, você deve começar a examinar mais de perto a pista PCIe envolvida em sua placa-mãe e como ela está possivelmente conectada a um soquete de CPU específico.

equilíbrio irqnormalmente faz um bom trabalho aqui, mas você pode configurar seu comportamento para atender às suas necessidades.

informação relacionada