Pergunta

É um fato conhecido que os aplicativos do Windows normalmente têm 2 GB de espaço de endereço privado em um sistema de 32 bits. Este espaço pode ser estendido para 3Gb com a opção / 3GB.

O sistema operacional em si o restante do 4Gb. Reservas

A minha pergunta é por quê?

Código em execução no modo kernel (ou seja, dispositivo de código do driver) tem seu próprio espaço de endereço. Por que, em cima de um espaço exclusivo endereço de 4GB, o sistema operacional ainda quer reservar 2Gb de cada processo do modo de usuário?

Eu pensei que a razão é a transição entre user-mode e de chamada no modo kernel. Por exemplo, uma chamada para NtWriteFile terá um endereço para a rotina de distribuição kernel (daí porque o sistema de reserva de 2 Gb em cada aplicação). Mas, usando SYSENTER, não é o número de serviço do sistema suficiente para o código de modo kernel para saber qual função / serviço está sendo chamado?

Se você pudesse esclarecer-me por isso que é tão importante para o sistema operacional para tomar 2Gb (ou 1Gb) de cada processo do modo de usuário.

Foi útil?

Solução

Dois processos de usuário diferentes têm diferentes espaços de endereços virtuais. Porque os mapeamentos de endereços virtual?physical são diferentes, o TLB cache é invalidada ao alternar contextos de um utilizador processar a outra. Isto é muito caro, pois sem o endereço já armazenado em cache no TLB, qualquer acesso à memória irá resultar em uma falha e uma caminhada do PTE s.

syscalls envolvem duas mudanças de contexto: user ? kernel, e depois do kernel ? usuário. A fim de acelerar o processo, é comum a reservar parte superior 1 GB ou 2 GB de espaço de endereço virtual para o uso do kernel. Porque o espaço de endereço virtual não muda através destas trocas de contexto, há ondas de TLB são necessárias. Isso é ativado por um pouco de usuário / supervisor em cada PTE, o que garante que a memória do kernel é somente enquanto acessível no kernelspace; userspace não tem acesso, mesmo que a tabela de páginas é o mesmo.

Se houvesse suporte de hardware para dois TLBs separados, com um exclusivamente para uso kernel, em seguida, essa otimização não seria mais útil. No entanto, se você tem espaço suficiente para se dedicar, é provavelmente mais interessante para fazer apenas uma maior TLB.

Linux em x86, uma vez apoiou um modo conhecido como "4G / 4G dividir". Neste modo, userspace tem pleno acesso a todo o espaço de endereço virtual de 4 GB, eo kernel também tem um espaço cheio de endereço virtual de 4 GB. O custo, como mencionado acima, é que todas syscall requer um flush TLB, juntamente com rotinas mais complexas para copiar dados entre o usuário ea memória do kernel. Este foi medida a impor-se a uma penalidade de desempenho de 30%.


Os tempos mudaram desde que esta pergunta foi originalmente feita e respondida: sistemas operacionais de 64 bits são agora muito mais prevalente. Em sistemas operacionais atuais sobre x86-64, endereços virtuais de 0 a 2 47 -1 (0-128TB) são permitidos para programas do usuário enquanto o kernel reside permanentemente dentro de endereços virtuais a partir de 2 47 × (2 17 -1) a 2 64 -1 (ou de -2 47 para -1, se você tratar endereços como inteiros assinados).

O que acontece se você executar um executável de 32 bits no Windows de 64 bits? Você poderia pensar que todos os endereços virtuais dos 0 aos 2 32 (0-4GB) seria facilmente disponíveis, mas, a fim de evitar a exposição de erros nos programas existentes, arquivos executáveis ??de 32 bits são ainda limitados a 0- 2 GB a menos que sejam recompilados com /LARGEADDRESSAWARE. Para aqueles que são, eles tenha acesso aos 0-4GB. (Isto não é uma nova bandeira, o mesmo aplicado em Windows de 32 bits kernels rodando com o interruptor /3GB, que mudou o 2G / 2G usuário / split kernel padrão para 3G / 1G, embora, é claro 3-4GB ainda estaria fora de range.)

Que tipos de erros pode haver? Como exemplo, suponha que você está implementando quicksort e têm dois ponteiros, a e apontando b no início e após o final de uma matriz. Se você escolher o meio como o pivô com (a+b)/2, ele vai trabalhar, desde que ambos os endereços estão abaixo de 2 GB, mas se eles são ambos acima, então a adição encontrará integer overflow eo resultado estará fora da matriz. (A expressão correcta é a+(b-a)/2.)

Como um aparte, Linux de 32 bits, com seu padrão do usuário 3G / 1G / split kernel, tem historicamente executar programas com sua pilha localizados na faixa 2-3GB, então qualquer um desses erros de programação teria provavelmente ser lavado rapidamente . 64-bit Linux dá 32-bit programas de acesso a 0-4GB.

Outras dicas

Windows (como qualquer OS) é muito mais do que os drivers do kernel +.

A sua aplicação depende de uma série de serviços mínimos que não existem apenas no espaço do kernel. Há um monte de buffers, puxadores e todos os tipos de recursos que podem obter mapeados para próprio espaço de endereço seu processo. Sempre que você chamar uma função Win32 API que retorna, digamos, um identificador de janela, ou uma escova, essas coisas têm que ser alocados em algum lugar no seu processo. Então, parte do Windows é executado no kernel, sim, outras partes executado em seus próprios processos de modo de usuário, e alguns, os que sua aplicação precisa de acesso directo a, são mapeados para o seu espaço de endereço. Parte disso é difícil de evitar, mas um fator adicional importante é o desempenho. Se todas Win32 chamada exigiu uma mudança de contexto, seria um grande impacto na performance. Se alguns deles podem ser tratados de usermode porque os dados que dependem já está mapeada para o seu espaço de endereço, a mudança de contexto é evitado, e você economizar muito poucos ciclos de CPU.

Assim, quaisquer necessidades OS alguns quantidade do conjunto de espaço de endereços de lado. Acredito Linux por conjuntos padrão apenas 1 GB para o sistema operacional.

A razão pela qual MS estabeleceram na 2GB com o Windows foi explicado no blog de Raymond Chen uma vez. Eu não tenho o link, e eu não me lembro os detalhes, mas a decisão foi tomada porque o Windows NT foi originalmente voltado para processadores Alpha, bem como, e em Alpha de, houve alguma boa razão para fazer o 50/50 Dividido. ;)

Foi algo a ver com o apoio da Alpha para 32, bem como código de 64 bits. :)

Código em execução no modo kernel (ie dispositivo de código do driver) tem o seu espaço de endereço próprio.

Não, não faz. Tem que compartilhar esse espaço de endereço com a parte modo de usuário de um processo em x86 processadores. É por isso que o kernel tem que suficiente espaço de reserva no total e finito o espaço de endereço.

Eu acredito que a melhor resposta é que os designers OS sentiu que no momento em que você tem que cuidar, as pessoas estariam usando Windows de 64 bits.

Mas aqui está um melhor discussão .

Parte da resposta tem a ver com a história de arquiteturas de microprocessador. Aqui está um pouco do que eu sei, outros podem fornecer detalhes mais recentes.

O processador Intel 8086 tinha uma arquitetura de deslocamento do segmento de memória, dando 20 endereços de memória de bits e memória física endereçável, portanto, total de 1MB.

Ao contrário de processadores concorrentes da época - como o Zilog Z80 - o Intel 8086 tinha apenas um espaço de endereço que teve de acomodar não só memória eletrônica, mas toda a comunicação de entrada / saída com esses periféricos menores como teclado, portas seriais, portas de impressora e monitores de vídeo. (Para efeitos de comparação, o Zilog Z80 tinham um espaço de endereços de entrada / saída separada com códigos de operação de montagem dedicados de acesso)

A necessidade de permitir espaço para uma gama cada vez maior de expansões periféricos levaram à decisão inicial de segmento do espaço de endereços na memória eletrônica de 0-640K, e "outras coisas" (input / output, ROMS, memória de vídeo etc) de 640 Kb até 1MB.

Como a linha x86 cresceu e evoluiu, e PCs evoluíram com eles, esquemas semelhantes têm sido utilizados, terminando com hoje 2G / 2G divisão do espaço de endereço 4G.

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top