Muitas vezes me confundo com o conceito de virtualização em sistemas operacionais. Considerando a RAM como a memória física, por que precisamos da memória virtual para executar um processo?
Onde fica essa memória virtual quando o processo (programa) do disco rígido externo é trazido para a memória principal (memória física) para a execução.
Quem cuida da memória virtual e qual é o tamanho da memória virtual?
Suponha que se o tamanho da RAM for 4 GB (ou seja, 2 ^ 32-1 espaços de endereço), qual é o tamanho da memória virtual?
Respostas:
A memória virtual é, entre outras coisas, uma abstração para dar ao programador a ilusão de ter memória infinita disponível em seu sistema.
Os mapeamentos de memória virtual são feitos para corresponder aos endereços físicos reais. O sistema operacional cria e lida com esses mapeamentos - utilizando a tabela de páginas, entre outras estruturas de dados para manter os mapeamentos. Os mapeamentos de memória virtual são sempre encontrados na tabela de páginas ou em alguma estrutura de dados semelhante (no caso de outras implementações de memória virtual, talvez não devêssemos chamá-la de "tabela de páginas"). A tabela de páginas também está na memória física - geralmente em espaços reservados pelo kernel que os programas do usuário não podem substituir.
A memória virtual é normalmente maior do que a memória física - não haveria muitos motivos para mapeamentos de memória virtual se a memória virtual e a memória física fossem do mesmo tamanho.
Apenas a parte necessária de um programa reside na memória, normalmente - este é um tópico chamado "paginação". A memória virtual e a paginação estão intimamente relacionadas, mas não são o mesmo tópico. Existem outras implementações de memória virtual, como segmentação.
Eu posso estar supondo que estou errado aqui, mas aposto que as coisas que você está achando difícil entender têm a ver com implementações específicas de memória virtual, provavelmente paginação. Não há uma maneira de fazer paginação - há muitas implementações e aquela que seu livro descreve provavelmente não é a mesma que aparece em sistemas operacionais reais como Linux / Windows - provavelmente há diferenças sutis.
Eu poderia tagarelar milhares de parágrafos sobre paginação ... mas acho que é melhor deixar para uma pergunta diferente direcionada especificamente a esse tópico.
fonte
Os softwares são executados no sistema operacional em uma premissa muito simples - eles requerem memória. O sistema operacional do dispositivo fornece isso na forma de RAM. A quantidade de memória necessária pode variar - alguns softwares precisam de muita memória, outros requerem memória insignificante. A maioria (senão todos) dos usuários executa vários aplicativos no sistema operacional simultaneamente e, como a memória é cara (e o tamanho do dispositivo é finito), a quantidade de memória disponível é sempre limitada. Assim, dado que todos os softwares requerem uma certa quantidade de RAM, e todos podem ser executados ao mesmo tempo, o sistema operacional tem que cuidar de duas coisas:
Agora a questão principal se resume a como a memória está sendo gerenciada. O que exatamente governa onde os dados pertencentes a um determinado software residirão na memória?
Vantagens:
Desvantagens:
Isso não escala. Teoricamente, um aplicativo pode exigir uma grande quantidade de memória quando está fazendo algo realmente pesado. Portanto, para garantir que nunca fique sem memória, a área de memória alocada a ele deve ser sempre maior ou igual a essa quantidade de memória. E se um software, cujo uso máximo teórico de memória é
2 GB
(portanto, exigindo2 GB
alocação de memória da RAM), for instalado em uma máquina com apenas1 GB
memória? O software deve simplesmente abortar na inicialização, informando que a RAM disponível é menor que2 GB
? Ou deve continuar e, no momento em que a memória necessária ultrapassar2 GB
, apenas abortar e sair com a mensagem de que não há memória suficiente disponível?Não é possível evitar a mutilação da memória. Existem milhões de softwares por aí, mesmo que cada um deles tivesse apenas
1 kB
memória, o total de memória necessária seria excedido16 GB
, o que é mais do que a maioria dos dispositivos oferece. Como podem, então, diferentes softwares receber slots de memória que não invadam as áreas uns dos outros? Em primeiro lugar, não existe um mercado centralizado de software que possa regular que quando um novo software está sendo lançado, ele deve atribuir a si mesmo essa quantidade de memória desta área ainda não ocupadae, em segundo lugar, mesmo que houvesse, não é possível porque o não. de softwares é praticamente infinito (exigindo memória infinita para acomodar todos eles), e a RAM total disponível em qualquer dispositivo não é suficiente para acomodar nem mesmo uma fração do que é necessário, tornando inevitável a invasão dos limites de memória de um software sobre o de outro. Então, o que acontece quando Photoshop é atribuído posições de memória1
para1023
e VLC é atribuído1000
a1676
? E se o Photoshop armazenar alguns dados no local1008
, o VLC sobrescrever isso com seus próprios dados e, posteriormente, o Photoshopacessa pensando que são os mesmos dados que estavam armazenados lá anteriormente? Como você pode imaginar, coisas ruins acontecerão.Então, claramente, como você pode ver, essa ideia é um tanto ingênua.
Digamos que o dispositivo acabou de ser ligado, o sistema operacional acabou de iniciar, no momento não há nenhum outro processo em execução (ignorando o sistema operacional, que também é um processo!) E você decide iniciar o VLC . Portanto, o VLC recebe uma parte da RAM dos endereços de byte mais baixo. Boa. Agora, enquanto o vídeo está sendo executado, você precisa iniciar seu navegador para visualizar alguma página da web. Em seguida, você precisa iniciar o Bloco de notas para rabiscar algum texto. E então Eclipse para fazer alguma codificação .. Logo sua memória
4 GB
é toda usada, e a RAM fica assim:Ok, agora que você decidiu que não precisa mais manter o Eclipse e o Chrome abertos, feche-os para liberar memória. O espaço ocupado na RAM por esses processos é recuperado pelo SO e se parece com isto agora:
Suponha que fechar esses dois libera
700 MB
espaço - (400
+300
) MB. Agora você precisa iniciar o Opera , que ocupará450 MB
espaço. Bem, você tem mais do que450 MB
espaço disponível no total, mas ... não é contíguo, é dividido em pedaços individuais, nenhum dos quais é grande o suficiente para caber450 MB
. Então você teve uma ideia brilhante, vamos mover todos os processos abaixo para o mais alto possível, o que deixará o700 MB
espaço vazio em um pedaço na parte inferior. Isso é chamadocompaction
. Ótimo, exceto que ... todos os processos que existem estão em execução. Movê-los significará mover o endereço de todo o seu conteúdo (lembre-se, o SO mantém um mapeamento da memória cuspida pelo software para o endereço de memória real. Imagine que o software cuspiu um endereço de45
com dados123
e o SO o armazenou no local2012
e criou uma entrada no mapa, mapeando45
para2012
. Se o software agora for movido na memória, o que costumava estar no local2012
não estará mais2012
, mas em um novo local, e o sistema operacional precisa atualizar o mapa de acordo para mapear45
para o novo endereço, para que o software possa obter os dados esperados (123
) ao consultar a localização da memória45
. No que diz respeito ao software, tudo o que ele conhece é esse endereço45
contém os dados123
!)! Imagine um processo que faz referência a uma variável locali
. No momento em que for acessado novamente, seu endereço mudou e ele não poderá mais encontrá-lo. O mesmo vale para todas as funções, objetos, variáveis, basicamente tudo tem um endereço, e mover um processo significará mudar o endereço de todos eles. O que nos leva a:Bem. Suponha que de alguma forma, de alguma maneira milagrosa, você consiga mover os processos para cima. Agora há
700 MB
espaço livre na parte inferior:O Opera se encaixa perfeitamente na parte inferior. Agora sua RAM se parece com isto:
Boa. Tudo parece bem. No entanto, não há muito espaço disponível e agora você precisa iniciar o Chrome novamente, um conhecido devorador de memória! Ele precisa de muita memória para iniciar e você quase não tem memória sobrando ... Exceto ... você agora percebe que alguns dos processos, que inicialmente ocupavam um grande espaço, agora não estão precisando de muito espaço. Pode ser que você tenha interrompido seu vídeo no VLC , portanto, ele ainda está ocupando algum espaço, mas não tanto quanto o necessário durante a execução de um vídeo de alta resolução. Da mesma forma para o bloco de notas e fotos . Sua RAM agora se parece com isto:
Holes
, de novo! De volta à estaca zero! Exceto, anteriormente, os buracos ocorriam devido ao encerramento de processos, agora são devido a processos que exigiam menos espaço do que antes! E você novamente tem o mesmo problema, osholes
combinados rendem mais espaço do que o necessário, mas eles estão espalhados, não muito úteis isoladamente. Portanto, você precisa mover esses processos novamente, uma operação cara e muito frequente, já que os processos freqüentemente reduzem de tamanho ao longo de sua vida útil.Tudo bem, então agora seu sistema operacional faz o necessário, move os processos e inicia o Chrome e, depois de algum tempo, sua RAM fica assim:
Legal. Agora, suponha que você volte a assistir Avatar no VLC . Sua necessidade de memória vai disparar! Mas ... não há espaço para crescer, pois o bloco de notas está aninhado em sua parte inferior. Portanto, novamente, todos os processos devem ser movidos para baixo até que o VLC encontre espaço suficiente!
Bem. Agora, suponha que o Fotos esteja sendo usado para carregar algumas fotos de um disco rígido externo. Acessar o disco rígido leva você do reino dos caches e RAM para o do disco, que é mais lento por ordens de grandeza. Dolorosamente, irrevogavelmente, transcendentalmente mais lento. É uma operação de E / S, o que significa que não está vinculada à CPU (é exatamente o oposto), o que significa que não precisa ocupar RAM agora. No entanto, ele ainda ocupa a RAM teimosamente. Se você quiser iniciar o Firefox nesse ínterim, não pode, porque não há muita memória disponível, ao passo que se o Fotos fosse tirado da memória durante sua atividade de I / O, ele teria liberado muita memória, seguido pela compactação (cara), seguida pelo encaixe do Firefox .
Então, como podemos ver, temos tantos problemas até com a abordagem da memória virtual.
Existem duas abordagens para lidar com esses problemas -
paging
esegmentation
. Deixe-nos discutirpaging
. Nessa abordagem, o espaço de endereço virtual de um processo é mapeado para a memória física em blocos - chamadospages
. Umpage
tamanho típico é4 kB
. O mapeamento é mantido por algo chamado depage table
, dado um endereço virtual, tudo o que agora temos que fazer é descobrir a quepage
o endereço pertence, em seguidapage table
, encontrar o local correspondente para aquelepage
na memória física real (conhecido comoframe
), e dado se o deslocamento do endereço virtual dentro dopage
é o mesmo para opage
e também para oframe
, descubra o endereço real adicionando esse deslocamento ao endereço retornado pelopage table
. Por exemplo:À esquerda está o espaço de endereço virtual de um processo. Digamos que o espaço de endereço virtual requer 40 unidades de memória. Se o espaço de endereço físico (à direita) também tivesse 40 unidades de memória, seria possível mapear todas as localizações da esquerda para uma localização à direita, e teríamos ficado muito felizes. Mas, por azar, não apenas a memória física tem menos (24 aqui) unidades de memória disponíveis, ela também deve ser compartilhada entre vários processos! Tudo bem, vamos ver como faremos com isso.
Quando o processo começa, digamos que uma solicitação de acesso à memória para localização
35
seja feita. Aqui, o tamanho da página é8
(cada umpage
contém8
locais, todo o espaço de endereço virtual dos40
locais, portanto, contém5
páginas). Portanto, este local pertence à página no.4
(35/8
). Dentro dissopage
, este local tem um deslocamento de3
(35%8
). Portanto, este local pode ser especificado pela tupla(pageIndex, offset)
=(4,3)
. Este é apenas o começo, então nenhuma parte do processo é armazenada na memória física real ainda. Assimpage table
, o , que mantém um mapeamento das páginas à esquerda para as páginas reais à direita (onde são chamadasframes
) está vazio no momento. Assim, o sistema operacional abre mão da CPU, permite que um driver de dispositivo acesse o disco e busque a página nº.4
para este processo (basicamente um pedaço de memória do programa no disco, cujos endereços variam de32
a39
). Quando chega, o sistema operacional aloca a página em algum lugar da RAM, digamos o próprio primeiro quadro, e opage table
para este processo toma nota de que a página4
mapeia para o quadro0
na RAM. Agora, os dados estão finalmente na memória física. O SO consulta novamente a tabela de páginas para a tupla(4,3)
e, desta vez, a tabela de páginas diz que a página4
já está mapeada para o quadro0
na RAM. Assim, o sistema operacional simplesmente vai para o0
º quadro na RAM, acessa os dados no deslocamento3
desse quadro (reserve um momento para entender isso.page
, que foi obtido do disco, é movido paraframe
. Portanto, seja qual for o deslocamento de um local de memória individual em uma página, ele será o mesmo no quadro também, já que dentro depage
/frame
, a unidade de memória ainda reside no mesmo lugar relativamente!) E retorna os dados! Como os dados não foram encontrados na memória na primeira consulta em si, mas tiveram que ser buscados do disco para serem carregados na memória, isso constitui um erro .Bem. Agora suponha que
28
seja feito um acesso à memória para localização . Tudo se resume a(3,4)
.Page table
agora tem apenas uma entrada, mapeamento de página4
para quadro0
. Portanto, isso é novamente uma falha , o processo cede a CPU, o driver do dispositivo busca a página do disco, o processo recupera o controle da CPU novamente e elepage table
é atualizado. Digamos que agora a página3
esteja mapeada para quadro1
na RAM. Assim,(3,4)
torna-se(1,4)
, e os dados nesse local na RAM é retornado. Boa. Dessa forma, suponha que o próximo acesso à memória seja por localização8
, que se traduz em(1,0)
. A página1
ainda não está na memória, o mesmo procedimento é repetido e opage
está alocado no quadro2
na RAM. Agora, o mapeamento do processo de RAM se parece com a imagem acima. Neste momento, a RAM, que tinha apenas 24 unidades de memória disponível, está cheia. Suponha que a próxima solicitação de acesso à memória para este processo seja do endereço30
. Ele mapeia para(3,6)
epage table
diz que a página3
está na RAM e mapeia para o quadro1
. Yay! Portanto, os dados são buscados no local da RAM(1,6)
e retornados. Isso constitui um sucesso , pois os dados necessários podem ser obtidos diretamente da RAM, sendo, portanto, muito rápidos. Da mesma forma, as próximas solicitações de acesso, digamos, por locais11
,32
,26
,27
todos são acertos , ou seja, dados solicitados pelo processo encontra-se diretamente na RAM sem a necessidade de procurar em outro lugar.Agora, suponha que uma solicitação de acesso à memória para localização
3
venha. Isso se traduz em(0,3)
, epage table
para este processo, que atualmente tem 3 entradas, para páginas1
,3
e4
diz que esta página não está na memória. Como nos casos anteriores, ele é obtido do disco; no entanto, ao contrário dos casos anteriores, a RAM está cheia! Então o que fazer agora? Aqui está a beleza da memória virtual, um quadro da RAM é despejado! (Vários fatores determinam qual quadro deve ser removido. Pode serLRU
baseado, onde o quadro que foi acessado menos recentemente para um processo deve ser removido. Pode ser afirst-come-first-evicted
base, onde o quadro que alocou há mais tempo, é removido, etc. .) Portanto, algum quadro é despejado. Diga o quadro 1 (apenas escolhendo aleatoriamente). No entanto, issoframe
é mapeado para algunspage
! (Atualmente, ele é mapeado pela tabela de página para página3
de nosso único processo). Portanto, esse processo tem que ser informado desta notícia trágica, aqueleframe
, que infelizmente pertence a você, é ser despejado da RAM para dar lugar a outropages
. O processo deve garantir que ele se atualizepage table
com essas informações, ou seja, removendo a entrada para aquela dupla de page-frame, para que na próxima vez que for feito um pedido para issopage
, ele diga corretamente ao processo que issopage
não está mais na memória , e deve ser obtido do disco. Boa. Assim, o quadro1
é removido, a página0
é trazida e colocada lá na RAM e a entrada da página3
é removida e substituída pelo0
mapeamento de página para o mesmo quadro1
. Portanto, agora nosso mapeamento se parece com isto (observe a mudança de cor no segundoframe
do lado direito):Viu o que aconteceu? O processo precisava crescer, precisava de mais espaço do que a RAM disponível, mas, ao contrário de nosso cenário anterior, onde todos os processos na RAM precisavam ser movidos para acomodar um processo crescente, aqui aconteceu com apenas uma
page
substituição! Isso foi possível pelo fato de que a memória de um processo não precisa mais ser contígua, pode residir em diferentes locais em blocos, o SO mantém as informações de onde eles estão e, quando necessário, são devidamente consultados. Observação: você pode estar pensando, hein, e se na maioria das vezes for ummiss
e os dados precisarem ser carregados constantemente do disco para a memória? Sim, teoricamente, é possível, mas a maioria dos compiladores são projetados da maneira que seguelocality of reference
, ou seja, se forem usados dados de algum local da memória, os próximos dados necessários estarão localizados em algum lugar muito próximo, talvez do mesmopage
,page
que acabou de ser carregado na memória. Como resultado, a próxima falha ocorrerá depois de algum tempo, a maioria dos requisitos de memória futuros serão atendidos pela página que acabou de ser trazida ou pelas páginas já na memória que foram usadas recentemente. Exatamente o mesmo princípio nos permite expulsar também o menos usado recentementepage
, com a lógica de que o que não foi usado por um tempo, provavelmente não será usado por um tempo também. Porém, nem sempre é assim e, em casos excepcionais, sim, o desempenho pode ser prejudicado. Mais sobre isso mais tarde.Legal. Anteriormente, estávamos enfrentando um problema em que, embora um processo seja reduzido em tamanho, o espaço vazio é difícil de ser recuperado por outros processos (porque isso exigiria uma compactação cara). Agora é fácil, quando um processo se torna menor em tamanho, muitos dos seus
pages
não são mais usados, então quando outros processos precisam de mais memória, umLRU
despejo baseado em simples despeja automaticamente aqueles menos usadospages
da RAM e os substitui pelas novas páginas de os outros processos (e claro atualizar opage tables
de todos esses processos, bem como o processo original que agora requer menos espaço), todos esses sem nenhuma operação de compactação cara!Quanto ao problema 2, pare um momento para entender isso, o cenário em si foi completamente removido! Não há necessidade de mover um processo para acomodar um novo processo, porque agora o processo inteiro nunca precisa caber de uma vez, apenas algumas páginas dele precisam caber ad hoc, o que acontece com o despejo
frames
da RAM. Tudo acontece em unidades depages
, portanto, não há conceito dehole
agora e, portanto, nenhuma questão de movimento! Dez de maiopages
tiveram que ser movidos devido a esse novo requisito, milhares dospages
quais foram deixados intactos. Considerando que, anteriormente, todos os processos (cada pedaço deles) tinham que ser movidos!Agora, quando o processo precisa fazer alguma operação de E / S, ele pode abandonar a CPU facilmente! O sistema operacional simplesmente remove todos os seus
pages
da RAM (talvez armazene-os em algum cache) enquanto novos processos ocupam a RAM nesse meio tempo. Quando a operação de I / O é feita, o SO simplesmente os restaurapages
para a RAM (claro, substituindo opages
de alguns outros processos, podem ser daqueles que substituíram o processo original, ou podem ser de alguns que precisam fazer I / Oh, agora, e, portanto, pode renunciar à memória!)E, claro, agora nenhum processo está acessando a RAM diretamente. Cada processo está acessando um local de memória virtual, que é mapeado para um endereço de RAM físico e mantido pelo
page-table
desse processo. O mapeamento é apoiado pelo sistema operacional, o sistema operacional permite que o processo saiba qual quadro está vazio para que uma nova página para um processo possa ser ajustada lá. Uma vez que esta alocação de memória é supervisionada pelo próprio sistema operacional, pode facilmente garantir que nenhum processo invada o conteúdo de outro processo, alocando apenas quadros vazios da RAM, ou ao invadir o conteúdo de outro processo na RAM, comunique-se com o processo para atualizá-lopage-table
.Então
paging
(entre outras técnicas), em conjunto com a memória virtual, é o que alimenta os softwares de hoje rodando em sistemas operacionais! Isso libera o desenvolvedor de software de se preocupar com quanta memória está disponível no dispositivo do usuário, onde armazenar os dados, como evitar que outros processos corrompam os dados de seu software, etc. No entanto, é claro, não é totalmente à prova. Existem falhas:Paging
é, em última análise, dar ao usuário a ilusão de memória infinita usando o disco como backup secundário. Recuperar dados do armazenamento secundário para caber na memória (chamadopage swap
, e o caso de não encontrar a página desejada na RAM é chamadopage fault
) é caro, pois é uma operação de E / S. Isso retarda o processo. Várias dessas trocas de página acontecem em sucessão, e o processo se torna dolorosamente lento. Você já viu seu software rodando bem e de repente ele se torna tão lento que quase trava, ou deixa você sem opção de reiniciá-lo? Possivelmente, muitas trocas de página estavam acontecendo, tornando-o lento (chamadothrashing
).Então, voltando ao OP,
Por que precisamos da memória virtual para executar um processo? - Como a resposta explica longamente, dar aos softwares a ilusão de que o dispositivo / SO tem memória infinita, de forma que qualquer software, grande ou pequeno, possa ser executado, sem se preocupar com a alocação de memória, ou outros processos que corrompam seus dados, mesmo quando correndo em paralelo. É um conceito, implementado na prática por meio de várias técnicas, uma das quais, conforme descrito aqui, é o Paging . Também pode ser segmentação .
Onde fica essa memória virtual quando o processo (programa) do disco rígido externo é trazido para a memória principal (memória física) para a execução? - A memória virtual não está em lugar nenhum por si, é uma abstração, sempre presente, quando o software / processo / programa é inicializado, uma nova tabela de páginas é criada para ele, e contém o mapeamento dos endereços cuspidos por aquele processo para o endereço físico real na RAM. Uma vez que os endereços cuspidos pelo processo não são endereços reais, em certo sentido, eles são, na verdade, o que você pode dizer
the virtual memory
,.Quem cuida da memória virtual e qual é o tamanho da memória virtual? - É cuidado, em conjunto, o SO e o software. Imagine uma função em seu código (que eventualmente foi compilada e transformada no executável que gerou o processo) que contém uma variável local - um
int i
. Quando o código é executado,i
obtém um endereço de memória na pilha da função. Essa função é armazenada como um objeto em outro lugar. Esses endereços são gerados pelo compilador (o compilador que compilou seu código no executável) - endereços virtuais. Quando executado,i
deve residir em algum lugar no endereço físico real para a duração dessa função, pelo menos (a menos que seja uma variável estática!), Então o sistema operacional mapeia o endereço virtual gerado pelo compiladori
em um endereço físico real, de modo que sempre que, dentro dessa função, algum código exigir o valor dei
, esse processo pode consultar o sistema operacional para esse endereço virtual e o sistema operacional por sua vez pode consultar o endereço físico para o valor armazenado e retorná-lo.Suponha que se o tamanho da RAM for 4 GB (ou seja, 2 ^ 32-1 espaços de endereço), qual é o tamanho da memória virtual? - O tamanho da RAM não está relacionado ao tamanho da memória virtual, depende do sistema operacional. Por exemplo, no Windows de 32 bits, sim
16 TB
, no Windows de 64 bits, sim256 TB
. Obviamente, também é limitado pelo tamanho do disco, já que é nele que é feito o backup da memória.fonte
Estou copiando descaradamente os trechos da página de manual do topo
fonte
Veja aqui: Memória Física Vs Memória Virtual
A memória virtual é armazenada no disco rígido e é usada quando a RAM está cheia. A memória física é limitada ao tamanho dos chips de RAM instalados no computador. A memória virtual é limitada pelo tamanho do disco rígido, portanto, a memória virtual tem capacidade para mais armazenamento.
fonte