Por que C domina no mercado de software embarcado? [fechadas]

14

Quase todo mundo agora diz a bênção:

desempenho !

Ok, C permite escrever código atlético. Mas existem outros idiomas que podem fazer isso, afinal! E o poder de otimização dos compiladores modernos é impressionante. Does C tem algumas vantagens que nenhuma outra língua tem? Ou simplesmente não há necessidade de instrumentos mais flexíveis no domínio?

videiras
fonte
1
FWIW, o Arduino pode ser controlado com C #: arduino.cc/playground/Interfacing/Csharp
FrustratedWithFormsDesigner
@ Frustrated: Sim, mas esse é um exemplo, e a maioria das pessoas que cria dispositivos usa o Arduino.
Ed S.
2
Veja também: stackoverflow.com/questions/1601893/…
Steve S
2
Veja também: stackoverflow.com/questions/812717/…
Steve Melnikoff
1
@ dan04, na grande maioria dos casos, isso não era realmente um problema. Um grupo de simulação 6DOF do Texas Instruments Defense Systems and Electronics Group fez um pequeno experimento em 1988. Até então, eles haviam feito todas as simulações no FORTRAN. Eles tentaram escrever um em PASCAL, para ver o quanto isso doeria. Eles descobriram que o PASCAL deu a eles um pequeno impacto no desempenho, mas o aumento da confiabilidade e a facilidade de depuração MAIS do que compensaram. Sem rodeios, eles descobriram que a forte verificação de tipo da PASCAL era uma coisa BOA. (E sim, eles estavam fazendo matrizes.)
John R. Strohm

Respostas:

41

Quase todo mundo agora diz a bênção:

desempenho!

Isso faz parte disso; o uso determinístico de recursos é importante em dispositivos com recursos limitados, mas existem outros motivos.

  1. Acesso direto a APIs de hardware de baixo nível.
  2. Você pode encontrar um compilador C para a grande maioria desses dispositivos. Isso não é verdade para nenhum idioma de alto nível na minha experiência.
  3. C (o tempo de execução e o executável gerado) é "pequeno". Você não precisa carregar um monte de coisas no sistema para executar o código.
  4. A (s) API (s) de hardware provavelmente serão gravadas em C ou C ++.
Ed S.
fonte
14
+1 Disponibilidade de compiladores. Quando estávamos escrevendo tudo em assembly, os primeiros compiladores gen foram enviados por Deus.
Christopher Bibbs
8
+1, acho que o uso determinístico de recursos está entre os motivos mais importantes. Você não tem muita memória para fazer todo o tipo de coleta de lixo sofisticada em uma máquina de lavar louça.
user281377
4
+1 também para "uso determinístico de recursos". Em muitos sistemas embarcados, esse requisito impede até o uso de alocação dinâmica de memória. Muitas outras linguagens dependem muito da alocação dinâmica de memória (mesmo muitos aspectos benéficos do C ++ precisam de memória dinâmica).
Michael Burr
2
Eu acrescentaria mais um ponto, que acaba sendo uma razão social e não técnica - acho que os desenvolvedores de software embarcados tendem a ser muito mais conservadores e resistentes à mudança do que outros desenvolvedores. Dependendo do seu ponto de vista, isso pode ser uma coisa boa ou ruim.
Michael Burr
1
Falando como um cara de sistemas, estou desconfiado de grandes abstrações. Eles são ótimos, até que parem de funcionar ou façam algo engraçado; nesse caso, pode ser uma enorme dor de cabeça para depurar. Isso não é algo que eu quero em um sistema de baixo nível.
Ed S.
18

O C foi projetado para modelar uma CPU, porque o C foi criado para tornar o Unix portátil em várias plataformas, em vez de apenas escrever a linguagem assembly.

Isso significa que os programas C funcionam bem como uma linguagem de programação para programas que precisam ter um nível de abstração muito próximo da CPU real, que é o caso do hardware incorporado.

Nota: C foi projetado por volta de 1970 e as CPUs eram mais simples.


fonte
3
+1: Esse é definitivamente o motivo. Talvez as pessoas tenham tentado projetar linguagens de alto nível mais recentes que capturam recursos dos processadores modernos, mas ninguém projetou uma linguagem para a qual ela se encaixa.
Ken Bloom
2
@ videiras, C é uma linguagem pequena com uma grande biblioteca de tempo de execução. Tudo isso pode ser feito na biblioteca de tempo de execução. Ele simplesmente não migra automaticamente para a biblioteca C padrão, por isso é específico da plataforma.
3
+1. C foi criado para e inicialmente usado em um PDP-7, que tinha no máximo 64kilowords de palavras de 18 bits. Muitas outras línguas "modernas" têm mais dificuldade em se encaixar nesse tipo de espaço. Especialmente para escrever um sistema operacional como o Unix.
greyfade 16/06
2
@ Greyfade: não é assim. O UNIX se originou no PDP-7, mas C não. Para citar o prefácio de The C Programming Language : "C foi originalmente projetado e implementado no sistema operacional UNIX no DEC PDP-11, de Dennis Ritchie".
Jerry Coffin
1
@ videiras: embora seja certamente razoável contemplar o suporte direto ao encadeamento na linguagem (cf, Concurrent C), grande parte do ponto de um cache é que ele torna as coisas mais rápidas sem nenhuma intervenção por parte do programador ou idioma.
Jerry Coffin
11

Uma razão para a dominação é que ela possui o tipo certo de ferramentas para a tarefa. Depois de ter desenvolvido em plataformas incorporadas em Java e C / C ++, posso dizer que a abordagem básica do C ++ é apenas mais natural. Salvar o desenvolvedor de sentir que ele está pulando nos aros porque a linguagem é de nível muito alto é uma coisa bastante irritante. Um bom exemplo é a ausência de variáveis ​​não assinadas em Java.

E os recursos úteis de VM / linguagens interpretadas geralmente não são viáveis ​​e são deixados de fora da implementação, por exemplo, coleta de lixo.

celebridade
fonte
3
"Java e C / C ++" - espero que você tenha significado "todos os três: Java C e C ++", pois C e C ++ são linguagens diferentes.
BЈовић
1
@ BЈовић: Respondendo anos depois para confirmar que sim, eu quis dizer todos os três. Eu estava usign ambos seguindo esta definição: "usado como uma palavra função para indicar e enfatizar a inclusão de cada uma das duas ou mais coisas" (duas ou mais coisas) :-)
celebdor
10

C requer muito pouco suporte de tempo de execução por si só, portanto a sobrecarga é muito menor. Você não gasta memória ou armazenamento no suporte ao tempo de execução, gasta tempo / esforço para minimizar esse suporte ou precisa permitir isso no design do seu projeto.

geekosaur
fonte
1
Realmente nunca acontece que você precise dessa funcionalidade e a reinvente? Por exemplo, grandes máquinas de estado construídas com switches são horríveis e as mesmas máquinas construídas com hierarquias de classe são agradáveis ​​e sustentáveis.
videiras
1
@ videiras - você normalmente tem um conjunto definido de entradas, máquinas de estado construídas em switch / se as escadas são mais claras e mais documentáveis ​​do que uma heiracrília de chamadas polimórficas mágicas dos bastidores.
Martin Beckett
2
@ Martin: para alguém com pouca experiência no desenvolvimento de OO, chamadas polimórficas não são "mágicas" nem "nos bastidores", e a noção de que declarações enormes de troca / se são mais claras e documentáveis ​​parece bizarra.
Michael Borgwardt
3
Descubra o que acontece quando o pin27 fica alto. Opção 1, procure "case PIN27:" A opção 2 rastreia um iterador sobre um mapa de functores para descobrir qual deles seria chamado de objetos PIN atribuídos ao pino 27 em tempo de execução. O problema com muito código OO é que a única maneira de lê-lo é essencialmente executá-lo. Em uma plataforma sem depuração em tempo de execução ou até um console que significa rastrear o código no papel ou na sua cabeça.
Martin Beckett
2
Ligeiramente tangente a essa discussão, há uma razão pela qual a lógica ladder (uma versão ainda mais primitiva switch, você poderia dizer) ainda é usada em muitos aplicativos incorporados. Mais fácil de depurar, mais fácil de verificar.
Geekosaur
9

Como mencionado em outras respostas, o C foi desenvolvido no início dos anos 70 para substituir a linguagem assembly em uma arquitetura de minicomputador. Naquela época, esses computadores geralmente custavam dezenas de milhares de dólares, incluindo memória e periféricos.

Atualmente, você pode obter a mesma ou maior potência do computador com um microcontrolador incorporado de 16 bits que custa quatro dólares ou menos em quantidades únicas - incluindo RAM incorporada e controladores de E / S. Um microcontrolador de 32 bits custa talvez um dólar ou dois a mais.

Quando estou programando esses pequenos, que é o que faço 90% do tempo em que não estou projetando as placas em que elas se assentam, gosto de visualizar o que o processador fará. Se eu pudesse programar rápido o suficiente no assembler, eu o faria.

Não quero todos os tipos de camadas de abstração. Costumo depurar percorrendo uma lista de dissimuladores na tela. É muito mais fácil fazer isso quando você escreve o programa em C, para começar.

tcrosley
fonte
1
Para alguns aplicativos incorporados, esse "dólar ou mais dois" é muito significativo. Ninguém vai notar o impacto no preço do carro, mas no termostato ou no CD player.
precisa
3
@ David Thornley, sim, concordo completamente, é por isso que atualmente tenho projetos com micros de 8, 16 e 32 bits, tudo ao mesmo tempo para diferentes clientes. (O consumo de energia é outra razão para ir com os dispositivos menores.)
tcrosley
1
O preço é determinado menos pelo custo do processador do que pela contagem de pinos. Placas são muito mais caras que chips.
Yttrill
7

Ele não domina inteiramente, pois o C ++ está sendo cada vez mais usado, pois os compiladores melhoraram e o desempenho do hardware aumentou. No entanto, C ainda é muito popular por alguns motivos;

  1. Amplo suporte. Praticamente todo fornecedor de chips fornece um compilador de corrente alternada e qualquer código de exemplo e drivers provavelmente serão escritos em c. Os compiladores C ++ são cada vez mais comuns, mas não um certificado morto para um determinado chip, e geralmente são mais complicados. Você também sabe que qualquer engenheiro incorporado poderá trabalhar em c. É a lingua franca da indústria.

  2. Atuação. Sim, você disse isso. O desempenho ainda é fundamental e em um ambiente em que as rotinas principais ainda são escritas no assembler, ou pelo menos otimizadas em c com referência à saída do assembly, nunca subestimam a importância disso. Muitas vezes, os alvos incorporados têm um custo muito baixo e têm memórias muito pequenas e poucos mips.

  3. Tamanho. C ++ tende a ser maior. Certamente, qualquer coisa usando o STL será maior. Geralmente, tanto em termos de tamanho do programa quanto em tamanho da memória.

  4. Conservadorismo. É uma indústria muito conservadora. Em parte porque os custos da falha geralmente são mais altos e a depuração geralmente é menos acessível, em parte porque não precisa ser alterada. Para um pequeno projeto incorporado c faz o trabalho bem.

Luke Graham
fonte
11
Veja, é o número 3 que parece ser um dos mitos mais prevalentes sobre o C ++. Escreva um contêiner de segurança de tipo para 5 tipos distintos em C e você causou pelo menos tanto inchaço quanto usar um único contêiner STL em 5 tipos distintos. Os programadores C resolvem isso escrevendo contêineres em tipos opacos (vazio *). Comparar ISSO a um modelo STL é um erro de categoria. Tenho que admitir que que ele é realmente um dos mais comuns "razões" para preferir C.
Edward Estranho
Concordo plenamente que, para replicar toda a funcionalidade em c, você acaba com a mesma área de cobertura que o c ++. A 'vantagem' de c é que ele permite que você seja seletivo. Em qualquer projeto significativo, eu preferiria usar c ++, mas às vezes o hardware de destino está restrito a um ponto em que isso não é prático. Dito isto, o número 1 é realmente a principal razão da minha experiência.
Luke Graham
6

Para sistemas embarcados, o principal é desempenho . Mas, como você disse, por que C e não outra linguagem de desempenho?

Até agora, muitas pessoas mencionaram a disponibilidade dos compiladores , mas ninguém mencionou a disponibilidade dos desenvolvedores . Muito mais desenvolvedores já conhecem C do que, digamos, OCaml.

Esses são os três figurões.

BlueRaja - Danny Pflughoeft
fonte
6

O software incorporado é muito diferente.

Em um aplicativo de desktop, abstrações e bibliotecas economizam muito tempo de desenvolvimento. Você tem o luxo de jogar outros megabytes ou gigabytes de RAM ou alguns núcleos de CPU de 2 + GHz e 64 bits em um problema, e outra pessoa (usuários) está pagando por esse hardware. Talvez você não saiba em quais sistemas o aplicativo será executado.

Em um projeto incorporado, os recursos geralmente são muito limitados. Em um projeto em que trabalhei (processadores da série PIC 17X), o hardware tinha 2Kwords de memória de programa, 8 níveis de pilha (no hardware) e 192 bytes (<0,2kB) de RAM. Diferentes pinos de E / S tinham recursos diferentes e você configurou o hardware conforme necessário, gravando nos registros de hardware. A depuração envolve um osciloscópio e analisador lógico.

No incorporado, as abstrações geralmente atrapalham e gerenciam (e custam) recursos que você não possui. Por exemplo, a maioria dos sistemas embarcados não possui sistema de arquivos. Os fornos de microondas são sistemas embarcados. Controladores de motor de carro. Algumas escovas de dente elétricas. Alguns fones de ouvido com cancelamento de ruído.

Um fator muito importante para mim no desenvolvimento de sistemas embarcados é conhecer e controlar o que o código traduz em termos de instruções, recursos, memória e tempo de execução. Frequentemente, a sequência exata de instruções controla, por exemplo, o tempo para as formas de onda da interface de hardware.

Abstrações e 'mágica' nos bastidores (por exemplo, um coletor de lixo) são ótimas para aplicativos de desktop. Os coletores de lixo economizam muito tempo procurando vazamentos de memória, quando a memória é / pode ser alocada dinamicamente.

No entanto, no mundo incorporado em tempo real, precisamos saber e controlar quanto tempo as coisas demoram, às vezes até nanossegundos, e não podemos jogar mais alguns meg de RAM ou uma CPU mais rápida em um problema. Um exemplo simples: ao fazer o escurecimento dos LEDs por software, controlando o ciclo de trabalho (a CPU tinha apenas o controle liga / desliga dos LEDs), NÃO está OK o processador desligar e fazer, por exemplo, coleta de lixo por 100ms, pois a tela seria visivelmente visível. piscar brilhante ou sair.

Um exemplo mais hipotético é um controlador de motor que aciona diretamente velas de ignição. Se essa CPU desligar e coletar lixo por 50ms, o motor será interrompido por um momento ou disparará na posição errada do virabrequim, potencialmente paralisando o motor (ao passar?) Ou danificando-o mecanicamente. Você pode matar alguém.

Technophile
fonte
Isso é tão verdadeiro quanto irrelevante para C - o problema a que você se refere é apenas o comportamento do GC ... O C ++ não possui nenhum GC e sabe o que? Eu, pessoalmente, usá-lo por causa das formações comentários e tipo mais rigoroso de segurança =)
videiras