Pourquoi les systèmes d'exploitation font-ils des choses de bas niveau en C et C ++? Pourquoi pas seulement C ++?

20

Sur la page Wikipedia pour Windows , il indique que Windows est écrit en assembleur pour le chargeur de démarrage et le sélecteur de tâches, et en C et C ++ pour les routines du noyau.

IIRC, vous pouvez appeler des fonctions C ++ à partir d'un extern "C"bloc 'd'. Je peux utiliser C pour les fonctions du noyau afin que les applications C pures puissent les utiliser (comme printfet telles), mais si elles peuvent simplement être enveloppées dans un extern "C "bloc, alors pourquoi coder en C?

Cole Johnson
la source
10
Avez-vous vu les différents "Pourquoi utiliser C quand il y a C ++?" des questions ici? Ce n'est pas nécessairement un double de l'un d'eux, mais ils sont liés.
1
"vous pouvez appeler des fonctions C ++ à partir d'un bloc" C "externe en C ++" Voulez-vous dire que vous pouvez appeler des fonctions C ...?
Code-Guru
@ Code-Guru non, car la seule différence entre les fonctions C et C ++ exportées est la décoration du nom et en C ++, l'ajout de la thisvariable
Cole Johnson
2
Lancez une exception dans un ISR et voyez ce qui se passe
James
Encore une autre question C contre C ++.
Machado

Réponses:

31

C'est principalement pour des raisons historiques. Certaines parties du noyau Windows ont été écrites à l'origine en C, car en 1983, il y a plus de trois décennies, lorsque Windows 1.0 a été déclenché , C ++ était à peine sorti. Maintenant, ces bibliothèques C y resteront "pour toujours", car Microsoft a fait de la rétrocompatibilité un argument de vente et la réécriture d'une version compatible avec les bogues des parties C en C ++ nécessite énormément d'efforts sans aucun avantage réel.

back2dos
la source
+1, je suppose que c'est la réponse la plus réaliste (en plus du fait qu'il pourrait y avoir des développeurs de noyau Windows qui n'aiment tout simplement pas C ++ ou ne font pas confiance aux compilateurs C ++ pour ces trucs de bas niveau). Regardez, par exemple, ici stackoverflow.com/questions/520068/… , pourquoi le noyau Linux est écrit en C.
Doc Brown
@ back2dos - Bien que leur code C ne soit pas jeté, cela ne signifie pas qu'il sera utilisé ou non mis à jour. Je vous garantis qu'il y a au moins une méthode qui fait quelque chose qui a été à l'origine écrit et contenu dans une bibliothèque C qui a été portée une bibliothèque C ++ dans Windows 8
Ramhound
8
J'ai du mal à croire qu'il existe un code Windows 1.0 dans toute version récente de Windows. Windows ME était la dernière version de Windows qui n'était pas basée sur la base de code Windows NT. Et même cela a été largement remplacé par le nouveau noyau RT (qui, si je comprends bien, ne promet pas grand-chose en termes de compatibilité descendante).
TMN
@TMN: l'argument est probablement correct non plus - je suis à peu près sûr sur la route de Win 1.0 à maintenant, il y avait beaucoup de bibliothèques écrites en C qui font toujours partie de la base de code actuelle de Win8, et personne chez MS n'en voit avantage à les réécrire en C ++.
Doc Brown
1
Il n'y a pratiquement aucun code qui parle au noyau Windows de toute façon. Fondamentalement, seuls les pilotes le font. Les applications parlent généralement à l'API Win32, ou éventuellement à l'API POSIX.
MSalters
24

Comme la plupart des gens l'ont souligné, les raisons sont de loin historiques, mais il y a autre chose que personne ne mentionne et je pense que c'est la raison pour laquelle les gens écrivent toujours du code C pour les bas niveaux.

C est un petit langage dans le sens où la spécification est (relativement) courte. C ++ est énorme et c'est un euphémisme. Cela peut ne pas être très important pour le programmeur (bien que je pense que oui), mais c'est extrêmement important si vous voulez faire une vérification formelle . De plus, il existe des outils établis pour l'analyse du code C, qui pourraient aider à prévenir les bogues, etc.

Et cela est très important dans les logiciels embarqués, où le coût d'un bogue qui est déployé est extrêmement élevé, par rapport au reste de l'industrie (comparez le Web, où vous pouvez appliquer un correctif immédiatement à tous les utilisateurs). Sans parler des logiciels critiques et des trucs médicaux.

Il y a eu des tentatives pour déplacer C de sa place dominante dans la programmation de bas niveau avec des langages encore meilleurs dans ce domaine, comme BitC, mais ils n'ont pas réussi jusqu'à présent.

K.Steff
la source
4
+1 Pour mentionner les logiciels critiques en C pur (par exemple les logiciels aéronautiques). Cependant, dans le logiciel médical, C ++ est également utilisé (des tests approfondis sont utilisés à la place d'une vérification formelle, ce qui serait extrêmement difficile en C ++).
Giorgio
1
De plus, C a un sous-ensemble sûr plutôt réussi MISRA-C. Il existe des équivalents pour C ++, mais ils ne sont pas (pour l'instant) standard de facto. La tendance dans la programmation critique pour la sécurité est que les bibliothèques et les compilateurs seront également obligés d'utiliser un sous-ensemble sûr comme MISRA. Réécrire une version compatible MISRA-C ++ de toute la bibliothèque standard C ++ sera très probablement un cauchemar.
2
Les directives @Lundin MISRA ne sont pas un sous-ensemble sûr - vous avez toujours des pointeurs bruts et la plupart des autres fonctionnalités qui rendent C dangereux - elles se concentrent principalement sur la non-utilisation ou la documentation du comportement spécifique à l'implémentation.
Pete Kirkham
@PeteKirkham MISRA-C interceptera tous les bogues de pointeur les plus classiques et imposera une analyse statique. Les normes de sécurité de l'industrie (IEC 61508 et al) approuvent apparemment MISRA-C comme un sous-ensemble sûr de C.Il n'y a pas beaucoup d'autres alternatives utiles pour les logiciels critiques, à moins que vous ne choisissiez SPARK Ada, une langue que peu connaissent, avec un outil limité soutien.
2
Cela aurait dû être sélectionné comme la meilleure réponse car c'est correct. D'autres qui suggèrent que le C n'est utilisé que pour des raisons historiques est hystérique en soi.
Rob
15
  1. Le runtime C est beaucoup plus petit.
  2. La traduction de C ++ en constructions de niveau inférieur est moins transparente qu'en C. (Voir références et vtables, pour deux exemples rapides)
  3. C a généralement un ABI stable. C ++ ne le fait généralement pas. Cela signifie qu'au minimum, l'interface d'appel système doit être de style C. De plus, si vous voulez n'importe quel type de modules dynamiques, avoir un ABI cohérent aide grandement.
wnoise
la source
+1 pour (2) et (3). Je ne suis pas convaincu avec (1).
Thomas Eding
7
@Thomas Eding: Le runtime C ++ se compose du runtime C, ainsi que des fonctionnalités C ++ telles que les exceptions, RTTI et un autre allocateur de mémoire. YMMV pour savoir si cela compte autant . (Et puis il y a la bibliothèque standard ...)
wnoise
Ah, j'ai oublié les exceptions et les pools nouveaux / supprimés. RTTI Je n'utilise jamais cependant: D
Thomas Eding
11

Les raisons ne sont pas techniques. Un peu d'assemblage est inévitable, mais ils ne sont pas obligés d'utiliser le C occasionnel, ils le veulent . Mon entreprise utilise son propre noyau propriétaire, écrit presque entièrement en C ++, mais nous n'avons pas besoin de prendre en charge une interface C vers le noyau comme la plupart des autres, car notre noyau intégré est compilé de façon monolithique avec nos applications C ++. Lorsque vous avez une interface C, il est souvent plus facile d'écrire le code d'interface en C, même s'il est possible de l'utiliser extern "C"pour l'écrire en C ++.

Même nous avons une poignée de fichiers C, principalement en raison de code tiers. Le code de bas niveau tiers est presque toujours fourni en C, car il est beaucoup plus facile d'incorporer du code C dans une application C ++ que l'inverse.

Karl Bielefeldt
la source
6

Les développeurs de noyau sont souvent le genre de personnes, qui se sentent plus heureux, quand il est immédiatement évident à la source, ce que fait réellement le code.

C ++ a beaucoup plus de fonctionnalités, qui cachent ce que fait le code plus que le code C simple: les surcharges, les méthodes virtuelles, les modèles, les références, les lancers ... C ++ a également beaucoup plus de syntaxe que vous devez maîtriser pour même comprendre le C ++ code en l'utilisant.

Je pense que la puissance de C ++ est un outil très puissant pour créer des bibliothèques et des frameworks, qui font ensuite du développement d'applications un jeu d'enfant. Très souvent, le développeur d'applications C ++ serait totalement perdu dans les entrailles remplies de modèles d'une bibliothèque, même lorsqu'il est très compétent pour créer des applications à l'aide de cette bibliothèque. Et l'écriture d'un droit de bibliothèque C ++ est une tâche de programmation très difficile, et uniquement effectuée afin de fournir un cadre idéal au profit du développeur d'applications. Les bibliothèques C ++ ne sont pas simples en interne, elles sont (ou peuvent être ...) juste puissantes mais simples du point de vue des programmeurs d'applications.

Mais l'API du noyau ne peut pas être une API C ++, elle doit être une API indépendante du langage, donc la plupart des bonnes choses en C ++ ne seraient pas directement utilisables à cette interface. De plus, le noyau n'est pas vraiment divisé en parties "bibliothèque" et "application" développées indépendamment, avec plus d'efforts allant logiquement à une bibliothèque, pour faciliter la création d'une masse d'applications.

De plus, la sécurité et la stabilité sont plus critiques à l'intérieur d'un noyau, et les méthodes virtuelles sont beaucoup plus dynamiques et donc beaucoup plus difficiles à isoler et à vérifier, que les rappels simples ou d'autres mécanismes de type C.

En bref, bien que vous puissiez bien sûr écrire n'importe quel programme C, y compris un noyau en C ++, la majeure partie de la puissance de C ++ n'est pas bien utilisée dans le noyau. Et beaucoup diraient que les outils de programmation devraient vous empêcher de faire des choses que vous ne devriez pas faire. C ++ ne le ferait pas.

hyde
la source
+1. En tant que développeur de noyau, ma «règle générale» est que si vous ne pouvez pas estimer facilement les «lignes de cache touchées», alors la langue que vous utilisez fait plus de mal que de bien.
Brendan
Clarification: Pour les noyaux, vous devez supposer que le processeur passe la plupart de son temps dans l'espace utilisateur et que le code du noyau est utilisé sporadiquement (par exemple lorsque l'espace utilisateur appelle l'API du noyau ou qu'une interruption se produit); ce qui signifie que vous devez assumer le "cache froid". Pour les CPU modernes (où la RAM est lente par rapport à la vitesse du CPU), le cache et les échecs TLB sont chers, donc (combinée avec l'attente de "cache froid"), la métrique "lignes de cache touchées" devient un indicateur extrêmement important pour les performances et / ou l'évolutivité.
Brendan
5

Bjarne Stroustrup, dans une interview en juillet 1999 :

Aucune de ces langues n'était radicalement différente ou dramatiquement meilleure que les autres langues contemporaines. Ils étaient cependant assez bons et les bénéficiaires de la chance et des facteurs sociaux

David
la source
2
Bienvenue David. Lorsque vous citez ou citez, c'est une bonne idée de fournir une référence (ajoutée!)
Andrew
3

C est un langage de très bas niveau, de par sa conception. C'est à deux pas de l'assembleur; connaissant le chipset que vous visez, vous pouvez, avec un peu de connaissances, «compiler» manuellement C en ASM. Ce type de langage "proche du métal" est essentiel pour de hauts niveaux d'optimisation (pour les performances, l'efficacité de la mémoire, etc.). Cependant, parce que c'est si proche du métal, vous n'obtenez pas beaucoup gratuitement avec cette langue; c'est un langage procédural, non orienté objet, et donc travailler avec de telles constructions implique beaucoup de code passe-partout pour créer et consommer des constructions à valeurs multiples en mémoire.

C ++ est "C one better", ajoutant un certain nombre de fonctionnalités faciles à utiliser telles que l'allocation dynamique de mémoire, le marshalling de structure intégré, une grande bibliothèque de code prédéfini, etc., au détriment de certaines pertes d'efficacité (encore beaucoup mieux que les environnements d'exécution gérés). Pour le codeur moyen, les avantages l'emportent largement sur les inconvénients dans les zones de la base de code qui ne nécessitent pas de contrôle anal-rétentif de l'allocation de mémoire, etc.

La combinaison des deux est assez traditionnelle; vous utilisez C pour écrire les zones de base de code les plus critiques en termes de performances et d'économie de mémoire, avec lesquelles vous pouvez ensuite travailler de manière plus abstraite via des appels de méthode à partir du code C ++, qui peuvent être organisés et conçus de manière plus élégante que l'ultra-performant. , un code C optimisé à toute épreuve.

KeithS
la source
2
En ce qui concerne l'efficacité, je vais me répéter: (1) Les gens en C ++ vous diront que c'est des conneries. (2) Je dis que je ne vois aucune raison pour que cela soit le cas et je voudrais des exemples concrets. Pas des exemples de la façon dont il est facile d'écrire du code moins efficace, mais des exemples de la façon dont être aussi efficace que C nécessite une laideur excessive.
3
Définissez "laid"; Je code en C # pour gagner ma vie, et chaque fois que je vois des exemples de code C ++ dans StackOverflow, je grince des dents à quel point la cruauté est considérée comme normale dans l'utilisation quotidienne du langage. Quand j'ai codé en C ++ il y a longtemps, j'ai souvent vu du code C et grincé des dents; types de structures d'emballage à la main, calculs de pointeurs d'exécution pour les sauts manuels, ASM intégré ... beurk. Certaines personnes déplorent la perte de connaissances de bas niveau chez les programmeurs Java / .NET; Je considère que c'est un énorme avantage pour la productivité.
KeithS
1
Vous n'avez pas répondu à ma question;) Par "moche" je veux dire "moche selon les normes des gourous C ++". En d'autres termes, des exemples où l'on ne peut pas utiliser "C ++ moderne" et être aussi efficace que C.
2
C'est peut-être vrai (honnêtement, je ne sais pas). Pour le développement du noyau (et quelques autres domaines), nous ne parlons pas de programmeurs moyens.
3
Les gens oublient que C -> C ++ est un continuum. Trop souvent, ces arguments comparent un bon C ++ moderne avec C. Vous pouvez prendre un programme C et le faire compiler avec un compilateur C ++ dans un temps relativement court et il fonctionnera exactement aussi vite. Si une fonctionnalité C ++ moderne est "trop ​​lente", ne l'utilisez pas. Cela peut même inclure des choses comme iostream. "Trop lent" n'est jamais une bonne excuse pour utiliser C sur C ++.
Gort le robot
1

Il se pourrait qu'avec C vous passiez la plupart de votre temps à réfléchir au problème à résoudre et à coder la solution. En C ++, vous finissez par penser au C ++ et à sa myriade de fonctionnalités, de fonctions et d'une syntaxe obscure.

Dans de nombreux magasins C ++, votre code est également surveillé par la "police de la mode" qui est fascinée par le dernier ensemble de modèles de conception ou les dernières déclarations inintelligibles du grand dieu Stroustrup. Le joli code devient plus valorisé que le code de travail, trouver une utilisation pour le dernier ensemble de modèles Boost est plus admiré que de trouver une solution de travail pour l'entreprise.

D'après mon expérience, pour toutes les fonctionnalités intelligentes et la pureté OO de C ++, le codage en C simple permet de faire le travail plus rapidement et plus efficacement.

James Anderson
la source
0

Il est possible que les parties C ne soient pas joliment portables pour le compilateur C ++ utilisé pour les parties C ++. Peut-être que le code C est délicieux avec le compilateur C d'une manière qui rompt avec le compilateur C ++.

Si vous avez un compilateur C ++ de qualité, il n'y a presque aucune raison de mélanger C et C ++ dans un projet. Presque.

La seule raison serait que votre projet partage le code C avec d'autres projets, le code ne se compile pas en C ++ et vous ne voulez pas conserver une fourchette C ++ de ce code.

Kaz
la source
-1

Je pense que vous l'avez à l'envers - le extern "C"bloc garantit que les conventions d'appel C sont utilisées pour toutes les fonctions du bloc. Vous pouvez donc appeler des fonctions C pures à partir de C ++, pas des fonctions C ++ à partir de C. Quoi qu'il en soit, j'imagine que la raison pour laquelle les gens utilisent à la fois C et C ++ est parce que beaucoup de bibliothèques de bas niveau sont écrites en C, et il est plus facile d'utiliser quelque chose qui existe déjà (et est probablement débogué et optimisé) que d'écrire le vôtre. OTOH, C ++ offre de nombreuses fonctionnalités de haut niveau avec lesquelles les gens préfèrent travailler, ils les utilisent donc pour le reste.

TMN
la source
-2

Il existe différents niveaux de plates-formes intégrées utilisant C comme langage de programmation (bien sûr, c'est votre liberté d'utiliser le langage d'assemblage à tout moment)

Pour 'Level', je parle du niveau de ressources SRAM et ROM internes pour un système.

Ces plates-formes sont parfois limitées en ressources (par exemple, certaines plates-formes 8051 n'ont que 128 octets de SRAM utilisateur).

Il est inutile de prendre en charge l'allocation de mémoire dynamique avec une si petite quantité de RAM. (nouveau / supprimer) ou même malloc en C.

L'une des principales améliorations du C au C ++ est le paradigme orienté objet. C ++ est adapté aux logiciels avec une plus grande empreinte mémoire

mais pas dans le firmware embarqué qui a sa limitation de taille jusqu'à 32 Ko. (par exemple dans une plate-forme MCU 16 bits)

Il n'est pas nécessaire d'avoir un compilateur C ++ qui est généralement plus compliqué que le compilateur C. (au moins les fournisseurs de SDK ne prendront pas la peine de le faire).

En fait, je peux difficilement trouver un compilateur C ++ sur une plate-forme ARM7 32 bits.

Cela ne vaut tout simplement pas la complexité

Dans certains 8051 (8 bits): 1 Mo de ROM, 128 Go de RAM

TI MSP430 (16 bits): ROM 32 Ko, RAM 4 Ko

ST Microelectronics ARM Cortex ™ -M3 CPU Core 32 bits (STM32F103T4): 16 ou 32 Ko de mémoire Flash 6 ou 10 Ko de SRAM

ansonchau
la source
2
Cela n'a rien de nouveau par rapport aux autres réponses déjà publiées ici.
Martijn Pieters
Un compilateur C ++ 32 bits pour ARM? Si vous le souhaitez, vous pouvez compiler vous-même LLVM à partir de la source après quelques modifications pour obtenir un compilateur C ++ pour iOS.
Cole Johnson
-4

Je vois deux raisons possibles:

  • C est un peu plus efficace par rapport à son équivalent C ++.
  • Certaines bibliothèques qu'ils utilisent sont écrites en C.
  • Ils utilisent certaines parties du noyau Linux, qui est écrit en C.

Modifié: Il s'avère que le troisième argument n'est pas vrai (voir les commentaires).

Pijusn
la source
5
(1) Les gens en C ++ ne seraient pas d'accord. Et objectivement, je ne vois aucune raison pour que cela soit le cas. (2) C ++ peut appeler très bien le code C (c'est tout l'intérêt de la compatibilité descendante et extern "C").
1
Si MS utilise certaines parties du noyau Linux et que le noyau Linux est GPL, cela ne signifierait-il pas que Windows devrait également être GPL?
TomJ
1
@TomJ en fait, c'est pourquoi ils ont également été obligés de faire don de quelques milliers de lignes à Linux. + Pourquoi pensez-vous qu'ils prennent en charge le développement Linux?
Pijusn
2
@Pius Son point est (et il a raison AFAIK), s'il y avait du code GPL lié au noyau Windows, le noyau entier devrait être GPL (à condition qu'il n'y ait pas d'accord séparé avec les détenteurs des droits d'auteur).
@delnan, pas sûr des détails. Je ne suis pas avocat et je ne peux donc pas commenter cela. Mais il y a eu un petit scandale il y a quelques années à ce sujet. Je ne sais pas, mais je pense que j'aurais pu être le module de mise en réseau de toutes les choses folles.
Pijusn du
-4

Parce que C est sans doute un meilleur langage que C ++. Et parce qu'une partie du code a été écrit avant que C ++ ne devienne populaire et que les gens n'aient aucune raison de le remplacer.

Et parce que C ++ possède de nombreuses fonctionnalités qui peuvent casser votre code si vous ne faites pas attention lors de son utilisation dans un noyau.

Minthos
la source
C ++ attend des bibliothèques dynamiques? Et qu'est-ce que la mémoire dynamique?
4
-1 pour [stuff] that C++ expects. Pourquoi C ++ utilise-t-il plus de tas que C? Pourquoi C ++ nécessite-t-il plus de DLL que C? Tout simplement PAS VRAI
Thomas Eding
1
Correction: vous perdez les bibliothèques écrites en C ++. Donc, c'est de retour à la case 1 si vous utilisez C ++ ou C. Pourquoi vous limiter à la fonctionnalité C si vous pouvez utiliser des modèles, des classes, des destructeurs, const et toutes sortes d'autres qualités.
Thomas Eding
6
Quelle? Les modèles, les exceptions, les objets (y compris les constructeurs, les destructeurs, les opérateurs surchargés, déplacent maintenant la construction et - pratiquement? - tout le reste), etc. fonctionnent très bien, peu importe d'où vient la mémoire (pile, mémoire statique, votre pool personnalisé ou autre) . Les conteneurs standard utilisent l'allocation de tas par défaut, mais leurs allocateurs peuvent être personnalisés et les gars du noyau écrivent quand même leurs propres collections et la gestion de la mémoire. -1
2
FYI: J'ai supprimé mon downvote parce que je ne pense pas que votre réponse soit activement nuisible à l'heure actuelle, mais je ne la considère pas particulièrement utile ou perspicace non plus.