Pourquoi C domine-t-il sur le marché des logiciels embarqués? [fermé]

14

Presque tout le monde va maintenant dire la bénédiction:

performance !

D'accord, C permet d'écrire du code athlétique. Mais il y a d'autres langues qui peuvent le faire, après tout! Et la puissance d'optimisation des compilateurs modernes est impressionnante. C a- t -il des avantages qu'aucun autre langage n'a? Ou tout simplement pas besoin d'instruments plus flexibles dans le domaine?

vignes
la source
1
FWIW, Arduino peut être contrôlé avec C #: arduino.cc/playground/Interfacing/Csharp
FrustratedWithFormsDesigner
@ Illustré: Oui, mais c'est un exemple, et la plupart des gens qui construisent des appareils utilisent Arduino.
Ed S.
2
Voir aussi: stackoverflow.com/questions/812717/…
Steve Melnikoff
1
@ dan04, dans la grande majorité des cas, ce n'était pas vraiment un problème. Un groupe de simulation 6DOF du Texas Instruments Defence Systems and Electronics Group a fait une petite expérience vers 1988. Jusque-là, ils avaient fait toutes leurs simulations sur FORTRAN. Ils ont essayé d'en écrire un dans PASCAL, pour voir à quel point cela ferait mal. Ils ont découvert que PASCAL leur a donné un petit coup de performances, mais l'augmentation de la fiabilité et la facilité de débogage PLUS que compensé. Franchement, ils ont trouvé que la vérification de type forte de PASCAL était une BONNE chose. (Et oui, ils faisaient des tableaux.)
John R. Strohm

Réponses:

41

Presque tout le monde va maintenant dire la bénédiction:

performance!

Cela en fait partie; l'utilisation déterministe des ressources est importante sur les appareils aux ressources limitées pour commencer, mais il y a d'autres raisons.

  1. Accès direct aux API matérielles de bas niveau.
  2. Vous pouvez trouver un compilateur C pour la grande majorité de ces appareils. Ce n'est pas vrai pour n'importe quelle langue de haut niveau dans mon expérience.
  3. C (le runtime et votre exécutable généré) est "petit". Vous n'avez pas à charger un tas de choses dans le système pour faire fonctionner le code.
  4. Les API / pilotes matériels seront probablement écrits en C ou C ++.
Ed S.
la source
14
+1 Disponibilité des compilateurs. À l'époque où nous écrivions tout dans l'assemblage, les premiers compilateurs de génération étaient un envoi divin.
Christopher Bibbs
8
+1, je pense que l'utilisation déterministe des ressources est l'une des raisons les plus importantes. Vous n'avez pas beaucoup de mémoire pour faire toutes sortes de collecte de déchets de fantaisie dans un lave-vaisselle.
user281377
4
+1 également pour "utilisation déterministe des ressources". Sur de nombreux systèmes embarqués, cette exigence empêche même l'utilisation de l'allocation dynamique de mémoire. De nombreux autres langages dépendent fortement de l'allocation dynamique de mémoire (même de nombreux aspects bénéfiques du C ++ nécessitent une mémoire dynamique).
Michael Burr
2
J'ajouterais un point de plus, qui se révèle être une raison sociale plutôt que technique - je pense que les développeurs de logiciels intégrés ont tendance à être beaucoup plus conservateurs et résistants au changement que les autres développeurs. Selon votre point de vue, cela peut être une bonne ou une mauvaise chose.
Michael Burr
1
En tant que gars des systèmes, je me méfie des grandes abstractions. Ils sont géniaux, jusqu'à ce qu'ils arrêtent de travailler ou fassent quelque chose de drôle, auquel cas cela peut être un énorme casse-tête de déboguer. Ce n'est pas quelque chose que je veux dans un système de bas niveau.
Ed S.
18

C a été conçu pour modéliser un CPU, car C a été créé pour rendre Unix portable sur toutes les plates-formes au lieu d'écrire simplement un langage d'assemblage.

Cela signifie que les programmes C fonctionnent bien en tant que langage de programmation pour les programmes qui doivent avoir un niveau d'abstraction très proche du CPU réel, ce qui est le cas pour le matériel embarqué.

Remarque: C a été conçu vers 1970 et les CPU étaient alors plus simples.


la source
3
+1: C'est certainement la raison. Peut-être que les gens ont essayé de concevoir de nouveaux langages de haut niveau qui capturent les fonctionnalités des processeurs modernes, mais personne n'a conçu un langage pour cela qui a fait son chemin.
Ken Bloom
2
@vines, C est un petit langage avec une grande bibliothèque d'exécution. Tout cela peut être fait dans la bibliothèque d'exécution. Il ne migre tout simplement pas automatiquement dans la bibliothèque C standard, il est donc spécifique à la plate-forme.
3
+1. C a été créé pour, et initialement utilisé sur un PDP-7, qui avait un maximum de 64 mots de mots de 18 bits. Beaucoup de langues plus «modernes» ont plus de mal à s’intégrer dans ce genre d’espace. Surtout pour écrire un OS comme Unix.
greyfade
2
@greyfade: pas vrai. UNIX est né sur le PDP-7, mais pas C. Pour citer la préface du langage de programmation C : "C a été initialement conçu et implémenté sur le système d'exploitation UNIX sur le DEC PDP-11, par Dennis Ritchie."
Jerry Coffin
1
@vines: bien qu'il soit certainement raisonnable d'envisager une prise en charge directe du threading dans le langage (cf, Concurrent C), l'essentiel d'un cache est qu'il accélère les choses sans aucune intervention de la part du programmeur ou du langage.
Jerry Coffin
11

Une des raisons de la domination est qu'elle dispose du bon type d'outils pour la tâche. Après avoir développé des plates-formes embarquées à la fois en Java et en C / C ++, je peux vous dire que l'approche nue jusqu'aux os de C ++ est tout simplement plus naturelle. Sauver le développeur de l'impression qu'il ou elle saute à travers des cerceaux parce que le langage est trop haut est assez ennuyeux. Un bon exemple est l'absence de variables non signées en Java.

Et les fonctionnalités pratiques des VM / langages interprétés ne sont généralement pas réalisables et sont exclues de l'implémentation, par exemple la collecte des ordures.

celebdor
la source
3
"Java et C / C ++" - j'espère que vous vouliez dire "tous les trois: Java C et C ++", car C et C ++ sont des langages différents.
BЈовић
1
@ BЈовић: Répondre des années plus tard pour confirmer que oui, je voulais dire tous les trois. J'utilisais les deux suivant cette définition: "utilisé comme mot de fonction pour indiquer et souligner l'inclusion de chacune de deux ou plusieurs choses" (deux ou plusieurs choses) :-)
celebdor
10

C nécessite très peu de support d'exécution en soi, donc la surcharge est beaucoup plus faible. Vous ne dépensez pas de mémoire ou de stockage sur le support d'exécution, ne dépensez pas de temps / effort pour minimiser ce support, ou ne devez pas en tenir compte dans la conception de votre projet.

geekosaure
la source
1
Ne vous arrive-t-il jamais vraiment d'avoir besoin de cette fonctionnalité et de la réinventer vous-même? Par exemple, les grandes machines d'état construites avec switches sont horribles, et les mêmes machines construites avec des hiérarchies de classes sont agréables et maintenables.
vignes
1
@vines - vous avez normalement un ensemble défini d'entrées, des machines à états construites sur le commutateur / si les échelles sont plus claires et plus documentables qu'une héritière de magie "en coulisse" des appels polymorphes.
Martin Beckett
2
@Martin: pour quelqu'un qui a peu d'expérience en développement OO, les appels polymorphes ne sont ni "magiques" ni "en coulisses", et l'idée que les énormes instructions switch / if sont plus claires et plus documentables semble carrément bizarre.
Michael Borgwardt
3
Trouvez ce qui se passe lorsque la broche 27 monte. Option 1, recherchez "case PIN27:" Option 2 tracez un itérateur sur une carte de foncteurs pour découvrir lequel serait appelé pour les objets PIN affectés à la broche 27 lors de l'exécution. Le problème avec beaucoup de code OO est que la seule façon de le lire est de l'exécuter essentiellement. Sur une plate-forme sans débogage au moment de l'exécution ou même sur une console, cela signifie suivre le code sur papier ou dans votre tête.
Martin Beckett
2
Légèrement tangente à cette discussion, il y a une raison pour laquelle la logique à relais (une version encore plus primitive de switch, pourrait-on dire) est toujours utilisée dans de nombreuses applications intégrées. Plus facile à déboguer, plus facile à vérifier.
geekosaur
9

Comme mentionné dans d'autres réponses, C a été développé au début des années 1970 pour remplacer le langage d'assemblage sur une architecture de mini-ordinateur. À l'époque, ces ordinateurs coûtaient généralement des dizaines de milliers de dollars, y compris la mémoire et les périphériques.

De nos jours, vous pouvez obtenir la même puissance informatique ou plus avec un microcontrôleur intégré 16 bits qui coûte quatre dollars ou moins en quantités uniques - y compris la RAM intégrée et les contrôleurs d'E / S. Un microcontrôleur 32 bits coûte peut-être un dollar ou deux de plus.

Quand je programme ces petits gars, ce que je fais 90% du temps lorsque je ne conçois pas les cartes sur lesquelles ils sont assis, j'aime visualiser ce que le processeur va faire. Si je pouvais programmer assez rapidement en assembleur, je le ferais.

Je ne veux pas toutes sortes de couches d'abstraction. Je débogue souvent en parcourant une liste de dissimulateurs à l'écran. C'est beaucoup plus facile de le faire lorsque vous avez écrit le programme en C pour commencer.

tcrosley
la source
1
Pour certaines applications intégrées, ce «dollar ou deux de plus» est très important. Personne ne remarquera l'impact sur les prix de leur voiture, mais ils le feront sur leur thermostat ou lecteur CD.
David Thornley
3
@David Thornley, oui, je suis entièrement d'accord, c'est pourquoi j'ai actuellement des projets en cours avec des micros 8, 16 et 32 ​​bits tous en même temps pour différents clients. (La consommation d'énergie est une autre raison pour aller avec les petits appareils.)
tcrosley
1
Le prix est moins déterminé par le coût du processeur que le nombre de broches. Les conseils sont beaucoup plus chers que les puces.
Yttrill
7

Il ne domine pas entièrement car C ++ est de plus en plus utilisé à mesure que les compilateurs se sont améliorés et les performances matérielles ont augmenté. Cependant, C est toujours très populaire pour plusieurs raisons;

  1. Large support. Presque tous les fournisseurs de puces fournissent un compilateur ac et tout exemple de code et de pilotes sera probablement écrit en c. Les compilateurs C ++ sont de plus en plus courants, mais pas un certificat mort pour une puce donnée, et ils sont souvent plus bogués. Vous savez également que tout ingénieur embarqué pourra travailler en c. C'est la lingua franca de l'industrie.

  2. Performance. Ouais, tu l'as dit. Les performances sont toujours roi et dans un environnement où les routines de base sont encore souvent écrites en assembleur, ou au moins optimisées en c en référence à la sortie de l'assemblage, ne sous-estimez jamais l'importance de cela. Souvent, les cibles intégrées sont très peu coûteuses et ont de très petites mémoires et peu de mips.

  3. Taille. C ++ a tendance à être plus gros. Certes, tout ce qui utilise la STL sera plus grand. Généralement à la fois en termes de taille de programme et d'empreinte mémoire.

  4. Conservatisme. C'est une industrie très conservatrice. En partie parce que les coûts d'échec sont souvent plus élevés et que le débogage est souvent moins accessible, en partie parce qu'il n'a pas eu besoin de changer. Pour un petit projet intégré, c fait bien le travail.

Luke Graham
la source
11
Vous voyez, c'est le n ° 3 qui semble être l'un des mythes les plus répandus autour du C ++. Écrivez un conteneur de type sécurisé pour 5 types distincts en C et vous aurez causé au moins autant de "ballonnement" que l'utilisation d'un seul conteneur STL sur 5 types distincts. Les programmeurs C contournent cela en écrivant des conteneurs sur des types opaques (void *). Comparer cela à un modèle STL est une erreur de catégorie. Je dois admettre que c'est en effet l'une des "raisons" les plus courantes de préférer C.
Edward Strange
Je suis entièrement d'accord que pour répliquer toutes les fonctionnalités de c, vous vous retrouvez avec la même empreinte que c ++. L '«avantage» de c est qu'il vous permet d'être sélectif. Sur tout projet important, je préférerais utiliser c ++, mais parfois le matériel cible est contraint à un point où ce n'est pas pratique. Cela dit, le n ° 1 est vraiment la principale raison de mon expérience.
Luke Graham
6

Pour les systèmes embarqués, la grande chose est la performance . Mais comme vous l'avez dit, pourquoi C et pas un autre langage performant?

Jusqu'à présent, beaucoup de gens ont mentionné la disponibilité des compilateurs , mais personne n'a mentionné la disponibilité des développeurs . Beaucoup plus de développeurs connaissent déjà C que, disons, OCaml.

Ce sont les trois biggies.

BlueRaja - Danny Pflughoeft
la source
6

Le logiciel embarqué est très différent.

Sur une application de bureau, les abstractions et les bibliothèques vous font gagner beaucoup de temps de développement. Vous avez le luxe de lancer un autre couple de mégaoctets ou gigaoctets de RAM ou des cœurs de processeur 64 bits 2 + GHz à un problème, et quelqu'un d'autre (les utilisateurs) paie pour ce matériel. Vous ne savez peut-être pas sur quels systèmes l'application fonctionnera.

Dans un projet intégré, les ressources sont souvent très limitées. Dans un projet sur lequel j'ai travaillé (processeurs PIC 17X), le matériel avait 2 000 mots de mémoire de programme, 8 niveaux de pile (dans le matériel) et 192 octets (<0,2 Ko) de RAM. Différentes broches d'E / S avaient des capacités différentes et vous avez configuré le matériel selon vos besoins en écrivant dans des registres matériels. Le débogage implique un oscilloscope et un analyseur logique.

En mode intégré, les abstractions gênent souvent et gèrent (et coûtent) les ressources que vous n'avez pas. Par exemple, la plupart des systèmes embarqués n'ont pas de système de fichiers. Les fours à micro-ondes sont des systèmes intégrés. Contrôleurs de moteur de voiture. Quelques brosses à dents électriques. Certains écouteurs antibruit.

Un facteur très important pour moi dans le développement de systèmes embarqués est de savoir et de contrôler ce que le code traduit en termes d'instructions, de ressources, de mémoire et de temps d'exécution. Souvent, la séquence exacte des instructions contrôle par exemple la synchronisation des formes d'onde de l'interface matérielle.

Les abstractions et la «magie» en arrière-plan (par exemple, un ramasse-miettes) sont idéales pour les applications de bureau. Les ramasse-miettes vous font gagner BEAUCOUP de temps à rechercher les fuites de mémoire, lorsque la mémoire est / peut être allouée dynamiquement.

Cependant, dans le monde intégré en temps réel, nous devons connaître et contrôler le temps nécessaire, parfois en nanosecondes, et nous ne pouvons pas jeter un couple de mégaoctets de RAM ou un processeur plus rapide en cas de problème. Un exemple simple: lors de la gradation logicielle des LED en contrôlant le rapport cyclique (le CPU n'avait que le contrôle on / off des LED), il n'est PAS OK pour le processeur de s'éteindre et de faire par exemple la collecte des ordures pendant 100 ms car l'affichage serait visiblement flash lumineux ou s'éteindre.

Un exemple plus hypothétique est un contrôleur de moteur qui déclenche directement des bougies d'allumage. Si ce processeur s'éteint et effectue la collecte des ordures pendant 50 ms, le moteur s'arrête un instant ou se déclenche à la mauvaise position du vilebrequin, ce qui pourrait caler le moteur (en passant?) Ou l'endommager mécaniquement. Vous pourriez faire tuer quelqu'un.

Technophile
la source
C'est tout aussi vrai que cela n'est pas pertinent pour C - le problème auquel vous faites référence n'est que le comportement du GC ... C ++ n'a pas de GC, et savez quoi? Je l'utilise personnellement en raison des commentaires de ligne et de la sécurité de type plus stricte =)
vignes