Eu estava pensando em minha introdução à programação recentemente e me lembrei de escrever um programa C++ que deliberadamente lia e gravava em endereços de memória aleatoriamente. Fiz isso para ver o que aconteceria.
Para minha surpresa, no meu PC com Windows 98, meu programa criava alguns efeitos colaterais muito estranhos. Ocasionalmente, alternava as configurações do sistema operacional ou criava falhas gráficas. Na maioria das vezes, não faria nada ou apenas travaria todo o sistema.
Mais tarde, descobri que isso acontecia porque o Windows 98 não restringia o que um processo de usuário tinha acesso. Eu podia ler e escrever na RAM usada por outros processos e até mesmo pelo sistema operacional.
É meu entendimento que isso mudou com o Windows NT (embora eu ache que demorou um pouco para acertar). Agora o Windows impede que você vasculhe na RAM que não pertence ao seu processo.
Lembro-me vagamente de executar meu programa em um sistema Linux mais tarde e não obter tantos resultados interessantes. Se bem entendi, isso se deve, pelo menos em parte, à separação do espaço do usuário e do kernel.
Então, minha pergunta é:
Houve uma época em que o Linux não separava o espaço do usuário e do kernel? Em outras palavras, houve um momento em que meu programa desonesto poderia ter causado estragos semelhantes em um sistema Linux?
O Linux sempre protegeu o kernel impedindo que o espaço do usuário acesse diretamente a memória que ele usa; também sempre protegeu os processos de acessar diretamente a memória uns dos outros. Os programas só podem acessar a memória através de um espaço de endereço virtual que dá acesso à memória mapeada para eles pelo kernel; o acesso fora da memória alocada resulta em uma falha de segmentação. (Os programas podem acessar o kernel por meio de chamadas de sistema e drivers, incluindo os infames
/dev/mem
e/dev/kmem
; eles também podem compartilhar memória entre si.)A MMU está dentro do kernel Unix/Linux? ou apenas em um dispositivo de hardware com memória própria? explica como a separação kernel/usuário é feita no Linux hoje em dia (as primeiras versões do Linux lidavam com isso de maneira diferente; consulte Visão geral do gerenciamento de memória do Linux e Gerenciamento de memória 80386 para obter detalhes).
Alguns projetos relacionados ao Linux removem essa separação; por exemplo , o Embeddable Linux Kernel Subset é um subconjunto do Linux compatível com a CPU 8086 e, como resultado, não oferece proteção imposta por hardware. O µClinux oferece suporte para sistemas embarcados sem unidade de gerenciamento de memória, e seus “ingredientes” principais agora fazem parte do kernel principal, mas tais configurações não são possíveis em arquiteturas “PC”.
Isso depende de como você define os termos "Linux", "espaço do usuário" e "espaço do kernel".
Lembre-se de como Linus Torvalds criou originalmente o Linux. Linus economizou algum dinheiro para comprar um PC (na época de última geração) com um CPU Intel 80386. Ele queria entender como o 80386 funciona e pensou que a melhor maneira de fazer isso seria escrever algum código de hardware de baixo nível em assembly 80386. Ao mesmo tempo, ele também estava insatisfeito com o desempenho do emulador de terminal rodando no Minix que ele estava usando para fazer login na universidade.
Então, ele decidiu escrever um emulador de terminal em assembly 80386 que você poderia inicializar diretamente. Para isso, ele precisava escrever um bootloader, um driver de teclado, um driver de exibição (de caractere), um driver serial e um driver para qualquer protocolo que ele usasse para se conectar à universidade.
Logo, ele descobriu que também queria baixar arquivos da universidade, então ele teve que implementar algum protocolo de transferência de arquivos (provavelmente ZMODEM, mas talvez ele tenha escolhido XMODEM por simplicidade) e também um driver de disco rígido, analisador de tabela de partição e um sistema de arquivos driver para o sistema de arquivos Minix. Como ele também queria continuar trabalhando enquanto o emulador de terminal executava alguma operação de longa duração (como um download de arquivo), ele implementou o multithreading.
Este é o ponto em que ele percebeu que já havia implementado algumas partes significativas de um sistema operacional e, portanto, pensou que seria outro projeto divertido transformar o emulador de terminal em um.
Em algum momento depois disso, ele acidentalmente digitou errado um comando e substituiu sua partição Minix por um backup. Agora ele tinha uma escolha a fazer: reinstalar o Minix ou terminar seu sistema operacional e usá-lo.
Quando ele chegou a um ponto em que seu sistema operacional era capaz de executar programas simples, ele decidiu carregá-lo para o servidor FTP da universidade e o nomeou Freax (ele achou que nomear algo com seu nome era pretensioso e arrogante). O administrador de sistema do servidor FTP não gostou do nome, porém, e decidiu renomear o arquivo para Linux, que ele achou que soava melhor.
Algum tempo depois, Linus fez a primeira menção pública do Linux em sua famosa mensagem, onde afirmou que o Linux estava tão ligado ao 80386 que nunca seria portátil para qualquer outra coisa e onde ele previu que o Linux nunca seria grande e profissional.
Agora, a questão é: em que ponto dessa jornada o "Linux" se tornou "Linux" e em que ponto dessa jornada o Linux se tornou um "kernel" para que falar sobre a separação do espaço do usuário e do kernel faça sentido?
Como eu disse no início: realmente depende de como você define esses termos.
Certamente houve um tempo em sua evolução em que o software que mais tarde se tornou um sistema operacional e que mais tarde foi chamado de "Linux" não tinha proteção, tinha serviços complexos o suficiente para que você pudesse chamá-lo de "kernel" e tinha independência suficiente subsistemas que você pode se safar chamando esses subsistemas de "programas". Por exemplo, em um sistema Unix "real", o emulador de terminal e a transferência de arquivos normalmente seriam dois programas separados e a coisa que coordena os dois e que abriga o código para acessar a porta serial, o disco rígido, a tela, o teclado, e o sistema de arquivos seria o kernel.
Mas esse software era "Linux"? Vou deixar isso para você decidir.
Sim, o Linux sempre precisou de um MMU para funcionar para proteção de memória. Muitas pessoas o portaram para pequenos sistemas embarcados sem MMU, mas não haverá mais proteção completa de memória, então um processo pode ler/gravar praticamente tudo