Programação da qualidade de serviço no SDV

A estrutura de agendamento de qualidade de serviço (QoS, na sigla em inglês) da SDV oferece alocação determinística de recursos da CPU para pacotes de serviços gerenciados pelo Lifecycle Manager (LM). Ao abstrair atributos de agendamento do Linux de baixo nível (política, prioridade, nice) em predefinições lógicas, a plataforma permite uma separação clara entre o desenvolvimento de serviços e o ajuste do sistema em todo o veículo. Isso ajuda a fornecer a largura de banda de computação necessária para cargas de trabalho sensíveis à segurança e ao tempo, enquanto o sistema restringe as tarefas em segundo plano para evitar instabilidade.

Funções e responsabilidades

O modelo de agendamento da SDV segue um padrão de responsabilidade delegada para ajudar a garantir que os serviços permaneçam portáteis, permitindo que o OEM ajuste o sistema.

Papel Responsabilidade Entrega principal
Plataforma SDV (Google) Define o esquema sdv_service_bundles_scheduling.proto, implementa a lógica de aplicação do LM e fornece a biblioteca de cliente sdv_service_bundles_scheduling. Definições de protobuf e bibliotecas de plataforma
OEM (integrador de sistemas) Define os valores concretos de cada predefinição, como o que ELEVATED significa em hardware específico, e controla a configuração em todo o sistema. /product/etc/lifecycle_config.textproto
Desenvolvedor de serviços Seleciona o nome da predefinição lógica apropriada e registra o caminho scheduling_config.textproto no manifesto do pacote de serviços. scheduling_config.textproto e sdv_service_bundles_manifest.textproto

Fluxo de trabalho técnico

  1. Integração da plataforma:o OEM define o lifecycle_config.textproto específico do veículo. Esse arquivo estabelece os perfis de agendamento em todo o sistema (predefinições) e os mapeia para atributos de agendamento concretos do Linux com base no hardware de destino.
  2. Desenvolvimento de pacotes de serviços:o desenvolvedor agrupa um scheduling_config.textproto no pacote APEX, recomendando uma predefinição lógica (por exemplo, ELEVATED) e definindo todos os nomes de linhas de execução internas.
  3. Integração de pacotes de serviços:durante a fase de integração do veículo, o OEM analisa a predefinição recomendada pelo desenvolvedor. O OEM pode manter o perfil recomendado ou substituí-lo, como fazer o downgrade de um serviço ELEVATED para NORMAL, para melhorar a estabilidade geral do sistema antes de assinar o APEX.
  4. Resolução de atributos de execução:quando um serviço é iniciado, o LM identifica a predefinição autorizada no manifesto do serviço e recupera os atributos correspondentes do Linux na configuração do sistema do OEM.
  5. Sincronização e aplicação de inicialização:o LM aplica os atributos resolvidos ao processo de serviço antes de sinalizar para continuar a execução usando o protocolo de sinalização e continuação.

Principais conceitos

Os conceitos a seguir são fundamentais para a estrutura de agendamento da SDV.

Predefinições de agendamento

As predefinições de agendamento são o principal mecanismo para gerenciar a QoS na SDV. Em vez de definir parâmetros de agendamento brutos do Linux, os desenvolvedores referenciam predefinições predefinidas por nome. No momento da execução, o LM mapeia esses nomes lógicos para atributos de agendamento concretos do Linux.

As predefinições a seguir são configuradas como um exemplo em lifecycle_config.textproto:

Nome da predefinição Política de agendamento Valor nice típico Caso de uso típico
NORMAL SCHED_OTHER 0 Serviços padrão (HVAC, mídia, configurações)
ELEVATED SCHED_OTHER -10 Componentes e infraestrutura do sistema principal
IDLE SCHED_IDLE 19 Análise em segundo plano e registro não crítico
CUSTOM Definido pelo usuário -20 (inicial) Serviços que exigem políticas ou afinidade em tempo real

Ao aplicar uma predefinição, o LM usa a chamada do sistema setpriority para definir o valor nice em todo o processo. Isso afeta a parte relativa da CPU que o processo recebe durante a disputa no Linux Completely Fair Scheduler (CFS) padrão.

Privilégio e segurança

Para evitar o aumento não autorizado de prioridade, a plataforma SDV emprega um modelo de segurança em camadas com base em domínios SELinux e recursos do Linux.

Domínios de segurança

  • untrusted_service_bundle: o domínio padrão para predefinições padrão (NORMAL, ELEVATED, IDLE). O kernel restringe processos nesse domínio, impedindo que eles mudem os próprios parâmetros de agendamento.
  • priority_service_bundle: concedido a qualquer pacote de serviços que use uma predefinição em que is_privileged: true esteja definido no lifecycle_config.textproto em todo o sistema. A transição para esse domínio concede ao processo o recurso CAP_SYS_NICE, permitindo que ele gerencie a própria alocação de recursos.

Recurso CAP_SYS_NICE

A plataforma concede o recurso CAP_SYS_NICE a processos no domínio priority_service_bundle. Essa permissão permite que um processo faça o seguinte:

  • Elevar o próprio valor nice além da atribuição inicial.
  • Mudar a política de agendamento para classes em tempo real, como SCHED_FIFO ou SCHED_RR.
  • Definir a afinidade da CPU usando sched_setaffinity.
  • Configurar parâmetros de prazo especializados para SCHED_DEADLINE.

Restringir esse recurso a um domínio dedicado protege o equilíbrio de agendamento em todo o sistema, limitando interrupções a serviços explicitamente autorizados.

Guia de configuração

Esta seção fornece orientações de configuração para OEMs e desenvolvedores de serviços.

Guia do OEM: predefinições em todo o sistema

O OEM define perfis de agendamento em /product/etc/lifecycle_config.textproto. A plataforma fornece um exemplo em lifecycle_management/config/lifecycle_config.textproto que os OEMs precisam ajustar com base no hardware do veículo.

Exemplo: definir uma predefinição em tempo real

Um OEM pode definir uma predefinição CRITICAL para serviços relacionados à segurança que nunca podem ser substituídos por aplicativos padrão:

# lifecycle_config.textproto
scheduling_presets {
  name: "CRITICAL"
  is_privileged: true
  thread_scheduling_configuration {
    policy: 1      # SCHED_FIFO
    priority: 80   # High real-time priority
  }
}

Guia do desenvolvedor: configuração do pacote de serviços

Os desenvolvedores de serviços recomendam uma predefinição e, opcionalmente, definem nomes de linhas de execução lógicas em um arquivo scheduling_config.textproto. Para ser descoberto pela plataforma, o caminho para esse arquivo precisa ser registrado em sdv_service_bundles_manifest.textproto.

Exemplo: registro de manifesto

# sdv_service_bundles_manifest.textproto
service_bundle_entries {
  name: "SensorService"
  scheduling_config_path: "configs/scheduling_config.textproto"
}

Exemplo: usar uma predefinição padrão

Para a maioria dos serviços, é suficiente referenciar um nome de predefinição no scheduling_config.textproto:

# configs/scheduling_config.textproto
scheduling_preset_name: "ELEVATED"

Exemplo: agendamento para linhas de execução de worker geradas pelo serviço

Um desenvolvedor de serviços pode criar linhas de execução de worker adicionais no código para lidar com tarefas especializadas, como um loop de dados do sensor de baixa latência. O desenvolvedor pode definir atributos de agendamento nomeados para essas linhas de execução internas no arquivo de configuração.

Use a aplicação manual apenas em serviços privilegiados que usam esses metadados para definir propriedades para as linhas de execução de worker internas:

# configs/scheduling_config.textproto
scheduling_preset_name: "CUSTOM"

# Map of logical thread names to their attributes (propagated as metadata)
thread_scheduling_configuration {
  key: "sensor-processing-thread"
  value {
    policy: 1        # SCHED_FIFO
    priority: 50
    cpu_affinity_ids: [2, 3]  # Pin to specific cores
  }
}

Comportamento e aplicação do sistema

A plataforma SDV emprega um modelo de aplicação rigoroso para ativar configurações de agendamento antes de executar qualquer código específico do serviço.

Sincronização de inicialização

Para evitar que um serviço seja executado com uma prioridade incorreta (mesmo durante a fase de inicialização), o LM e o Service Bundle Runner (SBR) usam um protocolo de sincronização de sinalização e continuação:

  1. Criação de processos:o LM bifurca o processo SBR. Nesse momento, o processo filho do SBR está em execução, mas entra imediatamente em um estado bloqueado, aguardando um sinal no stdin.
  2. Aplicação de atributos:enquanto o filho está bloqueado, o LM usa a chamada do sistema setpriority para aplicar o valor nice solicitado e configura a política de agendamento (por exemplo, SCHED_IDLE).
  3. Transição de segurança:o LM realiza a transição de domínio do SELinux, movendo o filho para o domínio untrusted_service_bundle ou priority_service_bundle.
  4. Sinal:somente depois que todos os parâmetros são aplicados, o LM envia um sinal de byte único para o stdin do filho.
  5. Execução:o SBR recebe o sinal e começa a carregar as bibliotecas de serviço e a chamar métodos de ciclo de vida.

Impacto na linha de execução principal e no ciclo de vida

Ao sincronizar antes de carregar as bibliotecas de serviço, a plataforma mantém a prioridade solicitada para a linha de execução principal em todos os callbacks do ciclo de vida:

  • onCreate: toda a injeção de dependência e a alocação inicial de recursos ocorrem na prioridade correta.
  • onStart: a predefinição rege a transição para o estado ativo e todos os loops de trabalho iniciais.
  • onStop e onDestroy: a plataforma realiza operações de revisão dos dados na mesma Prioridade para evitar atividades críticas do sistema durante o desligamento.

Pool de linhas de execução do Binder e herança de prioridade

As linhas de execução no pool de linhas de execução do Binder gerenciado pela plataforma não executam o trabalho com a prioridade da linha de execução que criou o pool. Em vez disso, para transações síncronas, a linha de execução do servidor herda a prioridade do autor da chamada. O driver do kernel do Binder controla esse mecanismo de herança de prioridade.

Ajuste de detalhes no nível da linha de execução

Os pacotes de serviços que exigem controle granular (por exemplo, loops de processamento em tempo real) precisam aplicar manualmente as configurações às linhas de execução de worker. Siga as etapas abaixo para aplicar configurações no nível da linha de execução:

  1. Solicite uma predefinição privilegiada (em que is_privileged: true esteja definido).
  2. Use a função get_scheduling_configuration da biblioteca sdv_service_bundles_scheduling para ler a thread_scheduling_configuration.
  3. Aplique atributos às linhas de execução de worker usando sched_setattr.

Aplicação de SELinux e recursos

A plataforma usa o SELinux e o recurso CAP_SYS_NICE do Linux para aplicar predefinições de agendamento:

  • Para serviços que usam predefinições como NORMAL ou IDLE, o agendamento é configurado pelo LM durante a inicialização. Esses serviços não têm o recurso CAP_SYS_NICE e não podem mudar a prioridade ou a política.
  • Os serviços que usam uma predefinição privilegiada (is_privileged: true) recebem o recurso CAP_SYS_NICE. Isso permite que eles controlem manualmente o agendamento das linhas de execução internas, conforme necessário para tarefas em tempo real.

Verificação e exemplos

A verificação do comportamento de agendamento exige uma combinação de análise de registros e medição de desempenho no nível do sistema. A plataforma SDV fornece um exemplo dedicado para demonstrar essas técnicas.

O exemplo de agendamento de QoS

Localizado em samples/qos_scheduling, esse exemplo inclui vários serviços de teste de desempenho projetados para serem executados em paralelo e informar o progresso.

  • PerformanceTesterNormal: é executado com a predefinição NORMAL.
  • PerformanceTesterElevated: é executado com a predefinição ELEVATED.
  • PerformanceTesterRealtime: usa a predefinição CUSTOM para aplicar SCHED_FIFO às linhas de execução de worker internas.
  • PolicyOffender: um serviço de diagnóstico que tenta definir uma prioridade em tempo real ao usar uma predefinição NORMAL. Isso é usado para verificar se a plataforma bloqueia o aumento não autorizado.

Executar o pacote de verificação

  1. Ative a configuração de orquestração específica da QoS:

    adb shell setprop persist.sdv.orchestrator_config_path /etc/orch/vm_qos_scheduling_orch_config.textproto

  2. Reinicialize o dispositivo para iniciar os serviços nos respectivos domínios de agendamento:

    adb reboot

  3. Filtre os registros para conferir os resultados comparativos de desempenho:

    adb logcat | grep sdv_sample_qos_common

    O serviço PerformanceTesterElevated informa unidades de trabalho concluídas significativamente maiores em comparação com PerformanceTesterNormal. Os erros de negação EPERM ou SELinux estão incluídos nos registros do serviço PolicyOffender.

Compatibilidade com versões anteriores

  • Para compatibilidade com versões anteriores, qualquer pacote de serviços legados que especifique um scheduling_config_path no manifesto, mas não especifique um scheduling_preset_name no arquivo de configuração, será tratado automaticamente como um serviço privilegiado. Isso preserva os recursos necessários (por exemplo, CAP_SYS_NICE) para serviços mais antigos que dependem do ajuste manual de linhas de execução.
  • A mensagem de configuração raiz DeadlineSchedulingConfiguration será renomeada em uma versão futura. O nome atual é histórico e não reflete mais com precisão que a mensagem processa todos os tipos de agendamento, não apenas o agendamento de prazo.