Um executável precisaria de um kernel do SO para ser executado?

53

Eu sei que quando o código-fonte, digamos C ++, é compilado, a saída do compilador é o código da máquina (executável) que eu pensei que fosse instruções diretamente para a CPU. Recentemente, eu estava lendo sobre kernels e descobri que os programas não podem acessar o hardware diretamente, mas precisam passar pelo kernel.

Portanto, quando compilarmos um código-fonte simples, digamos com apenas uma printf()função, e a compilação produzir o código de máquina executável, cada instrução nesse código de máquina será executada diretamente da memória (depois que o código for carregado na memória pelo sistema operacional) ou será cada comando no código da máquina ainda precisa passar pelo SO (kernel) a ser executado?

Eu li uma pergunta semelhante . Ele não explicou se o código da máquina gerado após a compilação é uma instrução diretamente para a CPU ou se será necessário passar novamente pelo kernel para criar a instrução correta para a CPU. Ou seja, o que acontece depois que o código da máquina é carregado na memória? Ele passará pelo kernel ou conversará diretamente com o processador?

GRANZER
fonte
29
Se você está escrevendo um código para um Arduino, não precisa de um sistema operacional.
23718 stib
12
printfnão é um ótimo exemplo. É explicitamente definido pela especificação C como uma função disponível apenas em implementações "hospedadas" (ou seja, executando em um kernel, em oposição a "autônomo", que pode não exigir uma). E na maioria das plataformas, printfé apenas uma função fornecida por você libcque faz um monte de coisas em seu nome (que eventualmente inclui um syscall para imprimir no stdout). Realmente não é diferente de chamar libvlc_media_list_add_mediaou PyObject_GetAttr, exceto que alguma printfimplementação é garantida como vinculável sem a adição de -ls não-padrão extras .
abarnert
11
Isso existe! (não afiliado, apenas pensei que era legal) erikyyy.de/invaders
Nonny Moose
9
Isso realmente depende da sua definição precisa dos termos "executável", "kernel", "executar", "precisar", "conversar com" e "passar". Sem uma definição precisa desses termos, a pergunta não pode ser respondida.
Jörg W Mittag 29/07
3
@ JörgWMittag - Se você vai ser pedante, por que está examinando apenas esses termos e apenas essa pergunta? O termo verdadeiramente saliente que precisa ser definido é "sistema operacional", que é aplicado questionavelmente ao MS-DOS (e ambientes de tempo de execução de tarefa única semelhantes). Se há algumas pessoas (mal informadas) que pensam que o BIOS do PC é um sistema operacional , então tudo está em jogo? Eu acho que não. O OP usa essas palavras em um contexto que parece razoável (especialmente se você não fala inglês nativamente) ou não técnico.
Serragem

Respostas:

86

Como alguém que escreveu programas executados sem um sistema operacional, ofereço uma resposta definitiva.

Um executável precisaria de um kernel do SO para ser executado?

Isso depende de como esse programa foi escrito e construído.
Você pode escrever um programa (supondo que tenha conhecimento) que não exija um sistema operacional.
Esse programa é descrito como autônomo .
Carregadores de inicialização e programas de diagnóstico são usos típicos para programas autônomos.

No entanto, o programa típico gravado e construído em algum ambiente do sistema operacional host será padronizado para execução no mesmo ambiente do sistema operacional host.
São necessárias decisões e ações muito explícitas para escrever e criar um programa independente.


... a saída do compilador é o código da máquina (executável) que eu pensei que eram instruções diretamente para a CPU.

Corrigir.

Recentemente, eu estava lendo sobre kernels e descobri que os programas não podem acessar o hardware diretamente, mas precisam passar pelo kernel.

Essa é uma restrição imposta por um modo de CPU que o sistema operacional usa para executar programas e facilitada por certas ferramentas de compilação, como compiladores e bibliotecas.
Não é uma limitação intrínseca a todos os programas já escritos.


Portanto, quando compilarmos um código-fonte simples, digamos com apenas uma função printf (), e a compilação produzir o código de máquina executável, cada instrução nesse código de máquina será executada diretamente da memória (assim que o código for carregado na memória pelo SO ) ou cada comando no código da máquina ainda precisará passar pelo SO (kernel) a ser executado?

Toda instrução é executada pela CPU.
Uma instrução que não é suportada ou é ilegal (por exemplo, o processo tem privilégios insuficientes) causará uma exceção imediata e a CPU executará uma rotina para lidar com essa condição incomum.

Uma função printf () não deve ser usada como um exemplo de "código fonte simples" .
A tradução de uma linguagem de programação de alto nível orientada a objetos para código de máquina pode não ser tão trivial quanto você sugere.
E então você escolhe uma das funções mais complexas de uma biblioteca de tempo de execução que realiza conversões de dados e E / S.

Observe que sua pergunta estipula um ambiente com um sistema operacional (e uma biblioteca de tempo de execução).
Depois que o sistema é inicializado e o sistema operacional recebe o controle do computador, são impostas restrições sobre o que um programa pode fazer (por exemplo, a E / S deve ser executada pelo sistema operacional).
Se você espera executar um programa independente (ou seja, sem um sistema operacional), não deve inicializar o computador para executar o sistema operacional.


... o que acontece depois que o código da máquina é carregado na memória?

Isso depende do meio ambiente.

Para um programa independente, ele pode ser executado, ou seja, o controle é entregue pulando para o endereço inicial do programa.

Para um programa carregado pelo sistema operacional, o programa precisa ser vinculado dinamicamente às bibliotecas compartilhadas das quais depende. O sistema operacional precisa criar um espaço de execução para o processo que executará o programa.

Ele passará pelo kernel ou conversará diretamente com o processador?

O código da máquina é executado pela CPU.
Eles não "passam pelo kernel" , mas nem "conversam com o processador" .
O código da máquina (que consiste em código operacional e operandos) é uma instrução para a CPU que é decodificada e a operação é executada.

Talvez o próximo tópico que você deva investigar seja o modo CPU .

serragem
fonte
2
"Se você espera executar um programa independente (ou seja, sem um sistema operacional), não deve inicializar o computador para executar o sistema operacional." não está totalmente correto. Muitos programas do DOS foram carregados após o DOS e depois ignoraram completamente os serviços do DOS (batendo diretamente em bits ou talvez chamando diretamente o BIOS). O Win3.x é um excelente exemplo que (exceto em alguns casos interessantes) ignorou que o DOS estava presente. O Win95 / 98 / Me também fez isso. Existem muitos exemplos de sistemas operacionais compatíveis com programas independentes, muitos da era dos 8/16 bits.
Eric Towers
8
@ EricTowers - Por "DOS" presumivelmente você quer dizer MS-DOS (desde que eu usei DOSes não relacionados à MS ou Intel)? Você está citando um "SO" que nem sequer corresponde aos critérios dos meus livros da faculdade de 1970 sobre conceitos e design de SO. As origens do MS-DOS remontam (através da Seattle Computer Products) ao CP / M, que explicitamente não é chamado de sistema operacional pelo seu autor Gary Kildall. FWIW, um sistema operacional que permite que um programa assuma o controle do sistema falhou em sua função básica de gerenciar os recursos do sistema. "Existem muitos exemplos de sistemas operacionais compatíveis com programas independentes" - "Suporte" ou incapaz de impedir?
sawdust
5
... ou ProDOS ou PC-DOS ou DR-DOS ou CBM DOS ou TRS DOS ou FLEX ...
Eric Torres
3
Gosto da terminologia "independente" do GCC. A palavra em inglês tem todas as conotações corretas para código executado sem um sistema operacional, talvez até melhor que "autônomo". por exemplo, você pode compilar gcc -O2 -ffreestanding my_kernel.c special_sauce.Spara criar um executável que não presuma que nenhuma das bibliotecas normais ou material do SO esteja lá. (Claro que você normalmente precisa de um script de vinculador para fazê-lo utilmente link em um formato de arquivo que um bootloader vai querer carga!)
Peter Cordes
4
@PeterCordes "autônomo" é o termo usado no padrão C que a IMO pode ser considerado autoritário. Alternativamente um bom termo também é "não-hospedado" (como em organizado pelo OS)
Jan Dorniak
38

O kernel é "apenas" mais código. Só que esse código é uma camada que fica entre as partes mais baixas do seu sistema e o hardware real.

Tudo é executado diretamente na CPU, você apenas passa por camadas dela para fazer qualquer coisa.

Seu programa "precisa" do kernel da mesma maneira que precisa das bibliotecas C padrão para usar o printfcomando em primeiro lugar.

O código real do seu programa é executado na CPU, mas as ramificações que o código faz para imprimir algo na tela passam pelo código da printffunção C , por vários outros sistemas e intérpretes, cada um dos quais faz seu próprio processamento para descobrir exatamente como hello world! realmente é impresso na tela.

Digamos que você tenha um programa de terminal executando em um gerenciador de janelas da área de trabalho, executando no seu kernel que, por sua vez, está sendo executado no seu hardware.

Há muito mais coisas acontecendo, mas vamos simplificar ...

  1. No programa do terminal, você executa o programa para imprimir hello world!
  2. O terminal vê que o programa gravou (através das rotinas de saída C) hello world!no console
  3. O programa do terminal vai até o gerenciador de janelas da área de trabalho, dizendo: "Fui hello world!escrito para mim, você pode colocá-lo em posição x, ypor favor?"
  4. O gerenciador de janelas da área de trabalho sobe para o kernel com "um dos meus programas quer que seu dispositivo gráfico coloque algum texto nessa posição, vá lá!"
  5. O kernel passa a solicitação para o driver do dispositivo gráfico, que o formata de uma maneira que a placa gráfica possa entender
  6. Dependendo de como a placa de vídeo estiver conectada, outros drivers de dispositivo do kernel precisam ser chamados para enviar os dados para barramentos físicos, como PCIe, lidando com coisas como garantir que o dispositivo correto seja selecionado e que os dados possam passar pela ponte ou conversores
  7. O hardware exibe coisas.

Esta é uma simplificação excessiva maciça apenas para descrição. Aqui estejam dragões.

Efetivamente, tudo o que você faz que precisa de acesso ao hardware, seja exibição, blocos de memória, bits de arquivos ou qualquer coisa assim, precisa passar por algum driver de dispositivo no kernel para descobrir exatamente como conversar com o dispositivo relevante. Seja um driver de sistema de arquivos em cima de um driver de controlador de disco rígido SATA, que está em cima de um dispositivo de ponte PCIe.

O kernel sabe como unir todos esses dispositivos e apresenta uma interface relativamente simples para os programas fazerem as coisas sem precisar saber como fazer elas mesmas.

Os gerenciadores de janelas da área de trabalho fornecem uma camada que significa que os programas não precisam saber desenhar janelas e jogar bem com outros programas que tentam exibir as coisas ao mesmo tempo.

Finalmente, o programa do terminal significa que seu programa não precisa saber como desenhar uma janela, nem conversar com o driver da placa gráfica do kernel, nem toda a complexidade relacionada ao lidar com buffers de tela e tempo de exibição e realmente mexer no linhas de dados para a tela.

Tudo é tratado por camadas e camadas de código.

Mokubai
fonte
Não apenas acesso a hardware , a maioria das comunicações entre programas também passa pelo kernel; o que normalmente não envolve pelo menos o kernel está configurando um canal mais direto. No entanto, para os fins da pergunta, também é possível e praticado em casos muito mais simples condensar todo o código em um único programa.
22718 Chris Stratton
De fato, seu programa de terminal nem precisa estar rodando na mesma máquina que o programa que está escrevendo coisas nele.
Jamesqf 28/07/19
Uma vez que pode precisar ser explicitamente declarado nesta pergunta - observe que quando falamos de programas "conversando" entre si, é metafórico.
User253751
21

Depende do ambiente. Em muitos computadores mais antigos (e mais simples!), Como o IBM 1401, a resposta seria "não". Seu compilador e vinculador emitiram um "binário" independente que era executado sem nenhum sistema operacional. Quando seu programa parou de ser executado, você carregou um programa diferente, que também era executado sem SO.

Um sistema operacional é necessário em ambientes modernos porque você não está executando apenas um programa por vez. Compartilhar o (s) núcleo (s) da CPU, a RAM, o dispositivo de armazenamento em massa, o teclado, o mouse e a tela, entre vários programas ao mesmo tempo, requer coordenação. O sistema operacional fornece isso. Portanto, em um ambiente moderno, seu programa não pode apenas ler e gravar o disco ou o SSD, ele precisa solicitar ao sistema operacional que faça isso em seu nome. O sistema operacional recebe essas solicitações de todos os programas que desejam acessar o dispositivo de armazenamento, implementa coisas como controles de acesso (não pode permitir que usuários comuns gravem nos arquivos do sistema operacional), enfileira-as no dispositivo e classifica as informações retornadas para os programas corretos (processos).

Além disso, os computadores modernos (ao contrário do, digamos, o 1401) suportam a conexão de uma variedade muito ampla de dispositivos de E / S, não apenas os que a IBM venderia para você nos velhos tempos. Seu compilador e vinculador não podem conhecer todas as possibilidades. Por exemplo, seu teclado pode estar conectado via PS / 2 ou USB. O sistema operacional permite instalar "drivers de dispositivo" específicos do dispositivo que sabem como conversar com esses dispositivos, mas apresentam uma interface comum para a classe de dispositivo no sistema operacional. Portanto, seu programa e até o sistema operacional não precisam fazer nada diferente para obter pressionamentos de teclas de um teclado USB versus PS / 2 ou para acessar, digamos, um disco SATA local ou um dispositivo de armazenamento USB ou um armazenamento que esteja em algum lugar fora em um NAS ou SAN. Esses detalhes são tratados pelos drivers de dispositivos dos vários controladores de dispositivos.

Para dispositivos de armazenamento em massa, o sistema operacional fornece sobre todos esses um driver de sistema de arquivos que apresenta a mesma interface para diretórios e arquivos, independentemente de onde e como o armazenamento é implementado. E, novamente, o sistema operacional se preocupa com controles de acesso e serialização. Em geral, por exemplo, o mesmo arquivo não deve ser aberto para gravação por mais de um programa por vez, sem passar por alguns obstáculos (mas leituras simultâneas geralmente são boas).

Portanto, em um ambiente moderno de uso geral, sim - você realmente precisa de um sistema operacional. Mas ainda hoje existem computadores como controladores em tempo real que não são complicados o suficiente para precisar de um.

No ambiente do Arduino, por exemplo, não existe realmente um sistema operacional. Claro, há um monte de código de biblioteca que o ambiente de construção incorpora em todos os "binários" que cria. Mas como não há persistência desse código de um programa para o outro, não é um sistema operacional.

Jamie Hanrahan
fonte
10

Eu acho que muitas respostas não entendem a pergunta, que se resume a isso:

Um compilador gera código de máquina. Esse código de máquina é executado diretamente por uma CPU ou é "interpretado" pelo kernel?

Basicamente, a CPU executa diretamente o código da máquina . Seria significativamente mais lento ter o kernel executando todos os aplicativos. No entanto, existem algumas ressalvas.

  1. Quando um sistema operacional está presente, os programas de aplicativos geralmente são impedidos de executar determinadas instruções ou acessar determinados recursos. Por exemplo, se um aplicativo executar uma instrução que modifica a tabela de interrupção do sistema, a CPU irá pular para um manipulador de exceções do SO para que o aplicativo incorreto seja encerrado. Além disso, os aplicativos geralmente não têm permissão para ler / gravar na memória do dispositivo. (Ou seja, "falando com o hardware".) Acessar essas regiões especiais de memória é como o sistema operacional se comunica com dispositivos como placa gráfica, interface de rede, relógio do sistema etc.

  2. As restrições que um SO impõe aos aplicativos são alcançadas por recursos especiais da CPU, como modos de privilégio, proteção de memória e interrupções. Embora qualquer CPU que você encontraria em um smartphone ou PC possua esses recursos, algumas CPUs não. Essas CPUs realmente precisam de kernels especiais que "interpretam" o código do aplicativo para alcançar os recursos desejados. Um exemplo muito interessante é o Gigatron , que é um computador com 8 instruções que você pode construir com chips que emula um computador com 34 instruções.

  3. Algumas linguagens como Java "compilam" algo chamado Bytecode, que não é realmente um código de máquina. Embora no passado eles fossem interpretados para executar os programas, hoje em dia algo chamado compilação Just-in-Time é normalmente usado, para que eles acabem sendo executados diretamente na CPU como código de máquina.

  4. A execução de software em uma máquina virtual costumava exigir que seu código de máquina fosse "interpretado" por um programa chamado Hypervisor . Devido à enorme demanda do setor por VMs, os fabricantes de CPU adicionaram recursos como o VTx às suas CPUs para permitir que a maioria das instruções de um sistema convidado seja executada diretamente pela CPU. No entanto, ao executar o software projetado para uma CPU incompatível em uma máquina virtual (por exemplo, emulando um NES), o código da máquina precisará ser interpretado.

Artelius
fonte
11
Embora o bytecode de Java normalmente não seja o código da máquina, ainda existem processadores Java .
Ruslan
Os hipervisores nunca foram sempre intérpretes. É claro que a interpretação é necessária se a máquina virtual como um conjunto de instruções incompatível com seu host, mas para a execução da mesma arquitetura, até os hipervisores iniciais executam código diretamente na CPU (você pode ficar confuso com a necessidade de kernels paravirtualizados, para CPUs sem o suporte do hipervisor necessário).
Toby Speight
5

Ao compilar seu código, você cria o chamado código "objeto" que (na maioria dos casos) depende das bibliotecas do sistema ( printfpor exemplo), então o código é envolvido por um vinculador que adiciona o tipo de carregador de programa que seu sistema operacional específico pode reconheça (é por isso que você não pode executar o programa compilado para Windows no Linux, por exemplo) e saiba como desembrulhar seu código e executar. Portanto, seu programa é como uma carne dentro de um sanduíche e só pode ser consumido como um pacote.

Recentemente, eu estava lendo o Kernels e descobri que os programas não podem acessar o hardware diretamente, mas precisam passar pelo kernel.

Bem, isso é meio caminho andado; se o seu programa for um driver no modo kernel, na verdade você poderá acessar diretamente o hardware se souber "conversar" com o hardware, mas geralmente (especialmente para hardware não documentado ou complicado) as pessoas usam drivers que são bibliotecas do kernel. Dessa forma, você pode encontrar funções da API que sabem como conversar com o hardware de maneira quase legível por humanos, sem a necessidade de saber endereços, registros, horários e várias outras coisas.

cada instrução neste código de máquina será executada diretamente da memória (depois que o código for carregado na memória pelo SO) ou cada comando no código de máquina ainda precisará passar pelo SO (kernel) a ser executado

Bem, o kernel é como garçonete, cuja responsabilidade é levá-lo a uma mesa e servi-lo. A única coisa que não pode fazer - é comer para você, você deve fazer isso sozinho. O mesmo acontece com o seu código, o kernel descompactará seu programa em uma memória e iniciará seu código, que é o código da máquina executado diretamente pela CPU. Um kernel só precisa supervisionar você - o que você tem permissão e o que não tem permissão para fazer.

ele não explica se o código da máquina gerado após a compilação é uma instrução diretamente para a CPU ou será necessário passar novamente pelo kernel para criar a instrução correta para a CPU?

O código de máquina gerado após a compilação é uma instrução diretamente para a CPU. Não há dúvida disso. A única coisa que você precisa ter em mente é que nem todo código no arquivo compilado é o código da máquina / CPU real. O Linker envolveu seu programa com alguns metadados que apenas o kernel pode interpretar, como uma pista - o que fazer com o seu programa.

O que acontece depois que o código da máquina foi carregado na memória? Ele passará pelo kernel ou conversará diretamente com o processador.

Se o seu código for apenas opcodes simples, como a adição de dois registradores, ele será executado diretamente pela CPU sem assistência do kernel, mas se o seu código usar funções de bibliotecas, essas chamadas serão assistidas pelo kernel, como no exemplo da garçonete, se você desejar para comer em um restaurante, eles dariam a você uma ferramenta - garfo, colher (e ainda são seus ativos), mas o que você fará com ela -, até o seu "código".

Bem, apenas para evitar chamas nos comentários - é realmente um modelo simplificado demais que espero ajudar o OP a entender as coisas básicas, mas boas sugestões para melhorar essa resposta são bem-vindas.

Alex
fonte
3

Portanto, quando compilarmos um código fonte simples, digamos com apenas uma função printf (), e a compilação produzir o código de máquina executável, cada instrução nesse código de máquina será executada diretamente da memória (uma vez que o código seja carregado na memória) pelo SO) ou cada comando no código da máquina ainda precisará passar pelo SO (kernel) a ser executado?

Essencialmente, apenas as chamadas do sistema vão para o kernel. Qualquer coisa a ver com E / S ou alocação / desalocação de memória geralmente resulta em uma chamada do sistema. Algumas instruções podem ser executadas apenas no modo kernel e farão com que a CPU desencadeie uma exceção. Exceções causam uma mudança para o modo kernel e um salto para o código do kernel.

O kernel não processa todas as instruções em um programa. Ele apenas faz chamadas e alterna entre os programas em execução para compartilhar a CPU.

Não é possível fazer alocação de memória no modo de usuário (sem o kernel); se você acessar a memória, não terá permissão para acessar, a MMU, previamente programada pelo kernel, notará e causaria uma exceção de "falha de segmentação" no nível da CPU. , que aciona o kernel, e o kernel mata o programa.

Não é possível executar E / S no modo de usuário (sem o kernel), se você acessar portas ou registros de E / S para dispositivos ou endereços conectados a dispositivos (um ou ambos necessários para executar qualquer E / S), eles acionam um exceção da mesma maneira.


Um executável precisaria de um kernel do SO para ser executado?

Depende do tipo de executável.

Os kernels, além de mediar o acesso compartilhado à RAM e ao hardware, também desempenham uma função de carregador.

Muitos "formatos executáveis", como ELF ou PE, possuem metadados no arquivo executável, além do código, e o trabalho do carregador é processá-lo. Leia os detalhes sangrentos sobre o formato PE da Microsoft para obter mais informações.

Esses executáveis ​​também fazem referência a bibliotecas ( arquivos de .dllobjetos compartilhados no Windows ou Linux .so) - seu código deve ser incluído.

Se o seu compilador produzir um arquivo que deve ser processado por um carregador do sistema operacional, e esse carregador não estiver lá, ele não funcionará.

  • Você pode incluir código que faça o trabalho do carregador?

Certo. Você precisa convencer o sistema operacional a executar, de alguma forma, seu código bruto sem processar nenhum metadado. Se o seu código chamar APIs do kernel, ele ainda não funcionará.

  • E se ele não chamar APIs do kernel?

Se você carregar este executável de alguma forma a partir de um sistema operacional (por exemplo, se ele permitir que o código bruto seja carregado e executado), ele ainda estará no modo de usuário. Se o seu código acessar coisas que são proibidas no modo de usuário, ao contrário do modo do kernel, como memória não alocada ou endereços / registros de dispositivos de E / S, ele trará falhas com privilégios ou violações de segmento (novamente, as exceções são para o modo kernel e são tratadas lá) e ainda não funcionará.

  • E se você executá-lo no modo kernel.

Então vai funcionar.


LawrenceC
fonte
Isso não é inteiramente correto. A exigência de que o acesso hardware passar pelo kernel, ou que há mesmo ser um kernel, é uma decisão de design feita de forma afirmativa em muitos sistemas hoje, mas também fez negativa (até hoje) em muitos sistemas simples.
22618 Chris Stratton
Estou explicando como estão as coisas se A) houver um kernel e B) se você estiver executando o código em uma CPU com o modo usuário / supervisor e uma MMU para ajudar a reforçar isso. Sim, existem CPUs e microcontroladores sem MMUs ou modo usuário / supervisor e sim alguns sistemas são executados sem o uso de toda a infraestrutura de usuário / supervisor. O primeiro Xbox da Microsoft foi assim - apesar de uma CPU x86 padrão com o modo usuário / supervisor, pelo que entendi nunca saiu do modo kernel - o jogo carregado poderia fazer o que quisesse.
28818 LawrenceC
11
O sistema Macintosh, antes do MacOS X, era um sistema operacional de um computador de uso geral , rodando na CPU de uso geral (família 68000, PowerPC) com suporte para proteção de memória por décadas (exceto os primeiros computadores baseados em 68000 que eu acho) que nunca usavam proteção de memória : qualquer programa pode acessar qualquer coisa na memória.
Curiousguy
3

TL; DR No.

O desenvolvimento do Arduino vem à mente como um ambiente atual em que não há sistema operacional. Confie em mim, em um desses bebês você não tem espaço para um sistema operacional.

Da mesma forma, os jogos para o Sega Genesis não tinham um sistema operacional fornecido pela Sega para serem acessados. Você acabou de criar seu jogo em montador de 68K, escrevendo diretamente para o bare metal.

Ou onde eu cortei os dentes, fazendo um trabalho incorporado no Intel 8051. Novamente, quando tudo o que você tem é uma 2716 eprom com uma área de 2k * 8, você não tem espaço para um sistema operacional.

Obviamente, isso pressupõe um uso muito amplo da palavra aplicativo. Como uma pergunta retórica, vale a pena se perguntar se um esboço do Arduino é realmente um aplicativo.

dgnuff
fonte
3

Embora eu não queira sugerir que as outras respostas não estejam corretas sozinhas, elas fornecem muitos detalhes que, receio, ainda são muito obscuros para você.

A resposta básica é que o código será executado diretamente no processador. E não, o código da máquina não "conversa" com ninguém, é o contrário. O processador é o componente ativo e tudo o que você faz no seu computador será feito por esse processador (estou simplificando um pouco as coisas aqui, mas tudo bem por enquanto). O processador irá ler o código e executá-lo e cuspir os resultados, o código da máquina é apenas um alimento para o processador.

Sua confusão decorre do uso da palavra hardware. Embora a divisão não seja tão clara como costumava ser, é melhor se você pensar em periféricos, em vez de simplesmente chamar tudo de hardware. Portanto, se houver um sistema operacional ou semelhante em sua máquina, seu programa precisará usar seus serviços para acessar os periféricos, mas o próprio processador não é periférico, é a principal unidade de processamento na qual seu programa é executado diretamente.

Kernels, sistemas operacionais e camadas intermediárias semelhantes geralmente são usados ​​apenas em sistemas maiores, onde há a expectativa de que vários programas sejam executados e é necessário que o sistema gerencie como esses programas podem usar os periféricos do computador (geralmente no mesmo tempo). Nesses casos, os programas em execução só podem acessar esses periféricos usando o sistema que decidirá como compartilhá-los e garantirá que não haja conflitos. Sistemas pequenos nos quais não há necessidade de gerenciamento entre os programas concorrentes, porque não existem, geralmente não possuem um sistema subjacente e o único programa normalmente em execução nesses sistemas é mais ou menos livre para fazer o que quiser com os periféricos.

Gábor
fonte
2

O BIOS que é executado no seu computador na inicialização é um código executável armazenado na ROM. Consiste em instruções da máquina e dados. Existe um compilador (ou montador) que monta este BIOS a partir do código fonte. Este é um caso especial.

Outros casos especiais incluem o programa de autoinicialização que carrega o kernel e o próprio kernel. Esses casos especiais geralmente são codificados em um idioma diferente de C ++.

No caso geral, é muito mais prático fazer com que o compilador produza algumas instruções que invocam os serviços do sistema fornecidos por um kernel ou por rotinas de biblioteca. Isso torna o compilador muito mais leve. Também torna o código compilado mais leve.

No outro extremo do espectro está o Java. Em Java, o compilador não converte o código fonte em instruções de máquina, pois esse termo geralmente é entendido. Em vez disso, o código-fonte é traduzido em "instruções da máquina" para uma máquina imaginária, chamada Java Virtual Machine. Antes que um programa Java possa ser executado, ele deve ser combinado com o tempo de execução do Java, que inclui um intérprete para a Java Virtual Machine.

Walter Mitty
fonte
2

Nos velhos tempos, seu programa era responsável por fazer tudo o que precisava ser feito durante a execução do seu programa, seja por você mesmo ou adicionando o código da biblioteca que outras pessoas escreviam em seu programa. A única coisa que funcionava ao lado disso no computador era o código para ler no seu programa compilado - se você tivesse sorte. Alguns computadores precisavam inserir código por meio de comutadores antes de poder fazer mais (o processo original de "inicialização"), ou mesmo todo o programa desse modo.

Foi rapidamente descoberto que era bom ter um código em execução capaz de carregar e executar o programa. Mais tarde, verificou-se que os computadores eram poderosos o suficiente para suportar a execução de vários programas ao mesmo tempo, alternando a CPU entre eles, especialmente se o hardware pudesse ajudar, mas com a complexidade adicional dos programas, não pisando nos dedos uns dos outros (por exemplo, , como lidar com vários programas que tentam enviar dados para a impressora de uma só vez?).

Tudo isso resultou em uma grande quantidade de código auxiliar sendo movida dos programas individuais para o "sistema operacional", com uma maneira padronizada de chamar o código auxiliar a partir de programas do usuário.

E é aí que estamos hoje. Seus programas executam a toda velocidade, mas sempre que precisam de algo gerenciado pelo sistema operacional, eles chamam de rotinas auxiliares fornecidas pelo sistema operacional, e esse código não é necessário e não está presente nos próprios programas do usuário. Isso incluía escrever no visor, salvar arquivos, acessar a rede etc.

Foram criados microkernels que fornecem exatamente o necessário para que um determinado programa seja executado sem um sistema operacional completo. Isso tem algumas vantagens para os usuários experientes, além de oferecer a maioria dos outros. Você pode ler a página da Wikipedia sobre o assunto - https://en.wikipedia.org/wiki/Microkernel - se quiser saber mais.

Eu experimentei um microkernel capaz de executar uma Java Virtual Machine, mas descobri mais tarde que o ponto ideal para isso é o Docker.

Thorbjørn Ravn Andersen
fonte
1

Nos sistemas operacionais típicos da área de trabalho, o próprio kernel é um executável. (Windows possui ntoskrnl.exe; Linux possui vmlinuxetc.) Se você precisasse de um kernel para que um executável fosse executado, esses sistemas operacionais não existiriam.

O que você precisa para um kernel é fazer as coisas que um kernel faz. Permita que vários executáveis ​​sejam executados ao mesmo tempo, apareça entre eles, abstraia o hardware, etc. A maioria dos programas não é capaz de fazer essas coisas por si só com competência, e você não gostaria que eles o fizessem. Nos dias do DOS - que mal podia ser chamado de sistema operacional - os jogos costumavam usar o sistema operacional como pouco mais que um carregador e acessavam diretamente o hardware como um kernel faria. Mas muitas vezes você precisava saber quais marcas e modelos de hardware estavam em sua máquina antes de comprar um jogo. Muitos jogos suportam apenas certas famílias de placas de vídeo e som e funcionam muito mal em marcas concorrentes, se funcionarem. Naquela'

cHao
fonte