Estou trabalhando em uma aplicação C++ no Ubuntu 20.04 que usa PCIe DMA para transferir dados de um buffer de espaço do usuário para o hardware. O buffer é mapeado para uma região fixa de 1K de memória física por meio de uma biblioteca personalizada (plib->copyDataToBuffer). Depois de chamar fork() e executar um processo filho (que apenas chama um programa externo e sai), notei que as gravações subsequentes no buffer pelo processo pai não são refletidas na memória física — o kernel ainda vê os dados antigos de antes da bifurcação.
Detalhes principais: O buffer de 1K é mapeado especificamente para DMA; ele é fixado e mapeado para um endereço físico conhecido.
Antes do fork(), uma chamada para plib->copyDataToBuffer atualiza corretamente a memória física.
Após fork(), o processo pai chama plib->copyDataToBuffer novamente com novos dados, e msync retorna sucesso, mas o conteúdo da memória física permanece inalterado.
O processo filho não toca no buffer; ele apenas executa um comando não relacionado via execvp.
Minhas suposições e preocupações: fork() causa COW (Copy-on-Write), mas como somente o pai grava no buffer, eu esperava que o conteúdo atualizado refletisse na memória física.
O comportamento do COW ou o remapeamento de memória pós-bifurcação podem estar interferindo nas regiões de memória mapeadas por DMA?
Confirmei que plib->copyDataToBuffer executa a gravação corretamente de uma perspectiva de software, mas o conteúdo real da memória física (verificado a partir do espaço do kernel) permanece obsoleto.
Pergunta: Por que a memória física que dá suporte ao meu buffer DMA retém dados obsoletos após um fork() + exec em um processo filho, mesmo que o pai grave novos dados depois?
Quais são as melhores práticas para garantir atualizações consistentes de memória física para buffers DMA em chamadas fork()?
man madvise
contém:Sugiro que você tente chamar
madvise (addr, length, MADV_DONTFORK)
os buffers antes de chamarfork
.Uma rápida olhada em memory.c do pacote rdma-core permite ver
MADV_DONTFORK
que está sendo usado, e essa biblioteca foi projetada para ter buffers de espaço do usuário bloqueados na memória física para DMA. Veja tambémman ibv_fork_init
.A página do manual citada
MADV_DONTFORK
diz que a cópia na gravação pode fazer com que o problema ocorra somente quando somente o pai grava no buffer.Parece que você espera
mmap
que a memória ed sobreviva a umaexec
chamada de sistema; esse não é o caso documentado (execve
(2)):