Citação de gerenciamento de memória do Kernel do Linux

1

Estou tendo um tempo incrivelmente difícil para entender este trecho do livro de drivers de dispositivos do Linux (desculpe pelo post pesado em texto):

The kernel (on the x86 architecture, in the default configuration) splits the 4-GB virtual address space between user-space and the kernel; the same set of mappings is used in both contexts. A typical split dedicates 3 GB to user space, and 1 GB for kernelspace.

Ok, entendi.

The kernel’s code and data structures must fit into that space, but the biggest consumer of kernel address space is virtual mappings for physical memory.

O que isso significa? O código e as estruturas de dados do kernel também não estão na "memória virtual mapeada para o espaço de endereço físico"? Caso contrário, onde essas estruturas de código e dados são armazenadas?

Ou isso está dizendo que o kernel precisa de espaço de endereço virtual para mapear dados aleatórios não relacionados ao kernel nos quais ele está operando via drivers, IPC ou o que for?

The kernel cannot directly manipulate memory that is not mapped into the kernel’s address space. The kernel, in other words, needs its own virtual address for any memory it must touch directly.

Isso é mesmo verdade? Se o kernel estiver rodando no contexto de um processo (manipulando um syscall), as tabelas de páginas do processo ainda serão carregadas, então por que o kernel não pode ler diretamente a memória do processo usermode?

Thus, for many years, the maximum amount of physical memory that could be handled by the kernel was the amount that could be mapped into the kernel’s portion of the virtual address space, minus the space needed for the kernel code itself.

Ok, se meu entendimento na citação # 2 estiver correto, isso faz sentido.

As a result, x86-based Linux systems could work with a maximum of a little under 1 GB of physical memory.

???? Isto parece ser um non sequitur completo. Por que não funciona com 4 GB de memória e apenas mapeia coisas diferentes no espaço de 1 GB disponível para o kernel, conforme necessário? Como o espaço do kernel sendo apenas ~ 1GB significa que o sistema não pode rodar com 4GB? Não precisa ser mapeado de uma só vez.

    
por David Davidson 05.07.2018 / 20:40

3 respostas

2

Why can't it work with 4GB of memory and just map different stuff into the 1GB space available for the kernel as needed?

Pode, é o que as opções HIGHMEM config fazem para a memória que não cabe ser mapeada diretamente. Mas quando você precisa acessar um local arbitrário na memória, é muito mais fácil fazer isso se você puder apontá-lo diretamente, sem configurar um mapeamento todas as vezes. Para isso, você precisa de uma área de memória virtual que seja sempre mapeada para toda a memória física, e isso não pode ser feito se o espaço de endereço virtual for menor que o físico.

O acesso direto também é mais rápido, vm/highmem.txt nos documentos do kernel diz:

The cost of creating temporary mappings can be quite high. The arch has to manipulate the kernel's page tables, the data TLB and/or the MMU's registers.

Claro, você pode acessar a memória do processo em execução por meio do mapeamento de espaço do usuário e, talvez, evitar a necessidade de acessar a memória de outros processos. Mas, se houver grandes estruturas de dados no kernel (como o cache de páginas), seria bom poder usar toda a memória para elas.

A coisa toda é uma espécie de troca de banco , que era algo que era usado em máquinas de 16 bits e em sistemas 386/486 na era DOS ( HIMEM.SYS ). Eu não acho que alguém tenha gostado particularmente de acessar a memória desse jeito, já que isso torna as coisas bastante difíceis se você precisar ter múltiplas áreas da memória física "abertas" ao mesmo tempo. Evoluir para sistemas de 32 bits e depois para sistemas de 64 bits eliminou esse problema.

    
por 05.07.2018 / 22:04
1

If the kernel is running in the context of a process (handling a syscall), the process' page tables will still be loaded, so why can't the kernel read usermode process memory directly?

O texto "o espaço de endereçamento do kernel" não deve, neste contexto, ser interpretado como oposto ao espaço de endereço do usuário. Em vez disso, o que significa é que a memória que o kernel precisa acessar deve ser mapeada para alguns endereços virtuais. Este é o ponto que o autor do livro está tentando fazer aqui. Assim, "o espaço de endereço do kernel" é todo o mapeamento.

    
por 05.07.2018 / 21:27
1

pode. "por muitos anos" isso não aconteceu; originalmente não havia razão para fazê-lo porque ninguém tinha tanta RAM.

você precisa continuar lendo um pouco mais, olhe com cuidado.

The limitation on how much memory can be directly mapped with logical addresses remains, however. Only the lowest portion of memory (up to 1 or 2 GB, depending on the hardware and the kernel configuration) has logical addresses;[2] the rest (high memory) does not. Before accessing a specific high-memory page, the kernel must set up an explicit virtual mapping to make that page available in the kernel's address space. Thus, many kernel data structures must be placed in low memory; high memory tends to be reserved for user-space process pages.

If the kernel is running in the context of a process (handling a syscall), the process' page tables will still be loaded, so why can't the kernel read usermode process memory directly?

faz

link

Também pode ser útil entender que o uso usual de kmalloc() para alocar estruturas no kernel retorna a memória que está dentro do mapeamento direto de ~ 1GB. Então, isso é lindo e direto de se acessar.

(A desvantagem é que ela introduz complexidade na forma desses diferentes tipos de alocação.

Se você quisesse que as alocações kmalloc() padrão usassem mais de 25% da RAM, estaria fazendo algo bastante exigente ... Em casos mais especializados, você pode definir o sinalizador GFP_HIGHMEM e mapear & desmapear a memória conforme necessário. Mas a resposta oficial é que você simplesmente não deveria tentar executar uma carga de trabalho tão exigente em sistemas legados de 32 bits recheados com mais de 30 bits de RAM física).

Se você está realmente interessado neste detalhe específico, notei duas outras coisas.

1. O limite de 1GB faz impor um limite na RAM, mas é um pouco maior.

link

A bit of googling indicates that the 4G:4G patch is needed for systems with a lot of RAM (eg. 32 GB or more) because the kernel memory tables scale with the size of physical memory and a 32 GB system uses 0.5 GB for the table, half the kernel space available to a 3G:1G system. A 64 GB system won't boot because all of kernel memory is needed for the table.

O patch 4G: 4G é outra coisa, mas você provavelmente pode ignorá-lo, não está no Linux principal.

Parece que essa limitação também foi superada, pois agora é possível ativar o CONFIG_HIGHMEM64G (em i386, ou seja, 32 bits). Provavelmente é melhor não confiar nisso. Ou pense muito sobre o que deve ser feito.

2. O mapeamento direto não é estritamente necessário para as tabelas de páginas.

Muitos tutoriais e explicações passo a passo para escrever um sistema operacional usam um truque alucinante chamado "tabelas de páginas recursivas".

link

O Linux não usou essa abordagem, então o Linux tradicional é mais simples de entender. O mapeamento direto da "baixa memória" de ~ 1GB é configurado na tabela de páginas inicial e nunca é alterado. E as tabelas de páginas são alocadas dentro de "pouca memória".

(Você está pensando sobre o que o CONFIG_HIGHMEM64G faz agora? Pare com isso, é ruim para você.)

Eu imagino que Linus simplesmente não pensou no truque recursivo. IIRC existem outras desvantagens de não ter um mapeamento direto bem dimensionado disponível também, mas não tenho certeza sobre exemplos específicos.

Eu digo "Linux tradicional". Não sei se o KPTI foi realmente fundido para 32 bits ainda ... mas, de qualquer forma, o KPTI não deve mudar a ideia geral. Depois de alternar do usuário para as tabelas de páginas do kernel, o kernel pode acessar o mapeamento direto. O processo de mudança é uma incrível magia negra, mas é simplesmente executada em cada mudança de contexto. As tabelas de páginas do espaço de usuário não incluem o mapeamento direto, mas o espaço do usuário não acessa e não deve acessar as tabelas de páginas, etc., então está tudo bem.

    
por 05.07.2018 / 21:04