Je sais que lorsque le code source, en C ++ par exemple, est compilé, le compilateur génère le code machine (exécutable) qui, à mon avis, était une instruction destinée au processeur. Récemment, j'étais en train de lire sur les noyaux et j'ai découvert que les programmes ne peuvent pas accéder directement au matériel, mais doivent passer par le noyau.
Ainsi, lorsque nous compilons un code source simple, par exemple avec juste une printf()
fonction, et que la compilation produit le code machine exécutable, chaque instruction de ce code machine sera-t-elle exécutée directement à partir de la mémoire (une fois que le code est chargé en mémoire par le système d'exploitation) ou chaque commande du code machine doit toujours passer par le système d'exploitation (noyau) pour être exécutée?
J'ai lu une question similaire . Il n'a pas expliqué si le code machine généré après la compilation est une instruction adressée directement à la CPU ou si elle devra de nouveau passer par le noyau pour créer la bonne instruction pour la CPU. Que se passe-t-il après le chargement du code machine dans la mémoire? Va-t-il passer par le noyau ou parler directement au processeur?
la source
printf
n'est pas un bon exemple. Il est explicitement défini par la spécification C comme une fonction uniquement disponible dans les implémentations "hébergées" (ce qui signifie s'exécuter sur un noyau, par opposition à "autonome", qui peut ne pas en nécessiter une). Et sur la plupart des plates-formes, ilprintf
s’agit simplement d’une fonction fournie par votre entrepriselibc
qui effectue un grand nombre de tâches en votre nom (qui inclut éventuellement un appel système à imprimer sur la sortie standard). Ce n'est vraiment pas différent d'appelerlibvlc_media_list_add_media
ouPyObject_GetAttr
, sauf que certainesprintf
implémentations sont garanties linkables sans ajouter des s non standard supplémentaires-l
.Réponses:
En tant que personne ayant écrit des programmes qui s'exécutent sans système d'exploitation, j'offre une réponse définitive.
Cela dépend de la façon dont ce programme a été écrit et construit.
Vous pouvez écrire un programme (en supposant que vous ayez les connaissances) ne nécessitant pas de système d'exploitation du tout.
Un tel programme est décrit comme autonome .
Les chargeurs de démarrage et les programmes de diagnostic sont des utilisations typiques des programmes autonomes.
Toutefois, le programme typique écrit et intégré dans un environnement de système d'exploitation hôte s'exécutait par défaut dans le même environnement de système d'exploitation hôte.
Des décisions et des actions très explicites sont nécessaires pour écrire et construire un programme autonome.
Correct.
Il s’agit d’une restriction imposée par un mode de processeur utilisé par le système d’exploitation pour exécuter des programmes, et facilitée par certains outils de compilation tels que les compilateurs et les bibliothèques.
Ce n'est pas une limitation intrinsèque à tous les programmes jamais écrits.
Chaque instruction est exécutée par la CPU.
Une instruction non prise en charge ou illégale (par exemple, le processus a des privilèges insuffisants) provoquera une exception immédiate et la CPU exécutera une routine pour gérer cette condition inhabituelle.
Une fonction printf () ne doit pas être utilisée comme exemple de "code source simple" .
La traduction d'un langage de programmation de haut niveau orienté objet vers le code machine risque de ne pas être aussi simple que vous l'imaginez.
Ensuite, vous choisissez l'une des fonctions les plus complexes d'une bibliothèque d'exécution qui effectue des conversions de données et des E / S.
Notez que votre question stipule un environnement avec un système d'exploitation (et une bibliothèque d'exécution).
Une fois le système démarré et le système d'exploitation donné à l'ordinateur, des restrictions sont imposées à ce qu'un programme peut faire (par exemple, les E / S doivent être effectuées par le système d'exploitation).
Si vous envisagez d'exécuter un programme autonome (c'est-à-dire sans système d'exploitation), vous ne devez pas démarrer l'ordinateur pour exécuter le système d'exploitation.
Cela dépend de l'environnement.
Pour un programme autonome, il peut être exécuté, c’est-à-dire que le contrôle est transféré en sautant à l’adresse de départ du programme.
Pour un programme chargé par le système d'exploitation, le programme doit être lié de manière dynamique aux bibliothèques partagées dont il dépend. Le système d'exploitation doit créer un espace d'exécution pour le processus qui exécutera le programme.
Le code machine est exécuté par la CPU.
Ils ne "passent pas par le noyau" , mais "ne parlent pas au processeur" .
Le code machine (composé du code d'opération et des opérandes) est une instruction de la CPU qui est décodée et l'opération effectuée.
Peut-être que le prochain sujet à examiner concerne les modes de processeur .
la source
gcc -O2 -ffreestanding my_kernel.c special_sauce.S
pour créer un fichier exécutable qui ne présuppose aucune des bibliothèques normales ou des éléments du système d’exploitation. (Bien sûr, vous auriez normalement besoin d'un script de l'éditeur de liens pour le lier utilement à un format de fichier qu'un chargeur de démarrage voudra charger!)Le noyau est "juste" plus de code. C'est simplement que ce code est une couche qui se situe entre les parties les plus basses de votre système et le matériel réel.
Tout s’exécute directement sur la CPU, il vous suffit de passer d’une couche à l’autre pour faire quoi que ce soit.
Votre programme "a besoin" du noyau de la même manière qu'il a besoin des bibliothèques C standard pour pouvoir utiliser la
printf
commande en premier lieu.Le code de votre programme s’exécute sur la CPU, mais les branches qu’il crée pour imprimer quelque chose à l’écran passent par le code de la
printf
fonction C , par le biais de divers autres systèmes et interpréteurs, chacun effectuant son propre traitement pour déterminer commenthello world!
est en fait imprimé sur votre écran.Supposons qu'un programme de terminal s'exécute sur un gestionnaire de fenêtres de bureau, sur votre noyau, lequel s'exécute à son tour sur votre matériel.
Il y a beaucoup plus qui se passe mais restons simples ...
hello world!
hello world!
sur la consolehello world!
écrit, pouvez-vous le mettre en placex
,y
s’il vous plaît?"C'est une simplification excessive pour la description seulement. Voilà des dragons.
En réalité, tout ce que vous faites a besoin d'un accès matériel, qu'il s'agisse d'affichage, de blocs de mémoire, de fichiers ou autre, doit passer par un pilote de périphérique du noyau pour déterminer comment communiquer avec le périphérique approprié. Qu'il s'agisse d'un pilote de système de fichiers au-dessus d'un pilote de contrôleur de disque dur SATA qui se trouve lui-même au-dessus d'un périphérique de pont PCIe.
Le noyau sait comment relier tous ces périphériques et présente une interface relativement simple permettant aux programmes de faire des choses sans avoir à savoir comment faire tout cela eux-mêmes.
Les gestionnaires de fenêtres de bureau fournissent une couche qui signifie que les programmes n'ont pas besoin de savoir dessiner les fenêtres et de bien jouer avec les autres programmes essayant d'afficher des éléments en même temps.
Enfin, le programme terminal signifie que votre programme n'a pas besoin de savoir dessiner une fenêtre, ni parler avec le pilote de la carte graphique du noyau, ni toute la complexité liée à la gestion des tampons d'écran et du minutage d'affichage et au brassage de la lignes de données à l'écran.
Tout cela est géré par des couches sur des couches de code.
la source
Cela dépend de l'environnement. Dans de nombreux ordinateurs plus anciens (et plus simples!), Tels que l’IBM 1401, la réponse serait «non». Votre compilateur et votre éditeur de liens ont émis un "binaire" autonome qui s’exécutait sans aucun système d’exploitation. Lorsque votre programme a cessé de fonctionner, vous en avez chargé un autre qui s’exécutait également sans système d’exploitation.
Un système d'exploitation est nécessaire dans les environnements modernes, car vous n'exécutez pas un seul programme à la fois. Le partage du ou des cœurs de la CPU, de la RAM, du périphérique de stockage de masse, du clavier, de la souris et de l’affichage entre plusieurs programmes à la fois nécessite une coordination. Le système d'exploitation fournit cela. Ainsi, dans un environnement moderne, votre programme ne peut pas simplement lire et écrire le disque ou le SSD, il doit demander à l'OS de le faire en son nom. Le système d'exploitation reçoit de telles demandes de tous les programmes souhaitant accéder au périphérique de stockage, implémente des éléments tels que les contrôles d'accès (impossible pour les utilisateurs ordinaires d'écrire dans les fichiers du système d'exploitation), les met en file d'attente sur le périphérique et trie les informations renvoyées. aux bons programmes (processus).
De plus, les ordinateurs modernes (contrairement au 1401, par exemple) prennent en charge la connexion d’une très grande variété de périphériques d’E / S, et pas seulement ceux qu’IBM vous vendrait autrefois. Votre compilateur et votre éditeur de liens ne peuvent pas connaître toutes les possibilités. Par exemple, votre clavier peut être interfacé via PS / 2 ou USB. Le système d'exploitation vous permet d'installer des "pilotes de périphérique" spécifiques à un périphérique qui savent comment communiquer avec ces périphériques, mais présentent une interface commune pour la classe de périphérique au système d'exploitation. Ainsi, votre programme, et même le système d'exploitation, n'a rien à faire pour obtenir des frappes au clavier USB / PS / 2, ou pour accéder, par exemple, à un disque SATA local, à un périphérique de stockage USB ou à un stockage quelque part sur un NAS ou un SAN. Ces détails sont gérés par les pilotes de périphérique des différents contrôleurs de périphérique.
Pour les périphériques de stockage de masse, le système d’exploitation fournit à tous ceux-ci un pilote de système de fichiers qui présente la même interface avec les répertoires et les fichiers, quel que soit l’emplacement et la façon dont le stockage est implémenté. Et encore une fois, le système d'exploitation s'inquiète des contrôles d'accès et de la sérialisation. En général, par exemple, le même fichier ne devrait pas être ouvert pour l'écriture par plus d'un programme à la fois sans sauter quelques étapes (mais les lectures simultanées sont généralement acceptables).
Donc, dans un environnement polyvalent moderne, oui, vous avez vraiment besoin d'un système d'exploitation. Mais même aujourd'hui, il existe des ordinateurs tels que les contrôleurs temps réel qui ne sont pas assez compliqués pour en avoir besoin.
Dans l'environnement Arduino, par exemple, il n'y a pas vraiment de système d'exploitation. Bien sûr, il y a un tas de code de bibliothèque que l'environnement de construction incorpore dans chaque "binaire" qu'il construit. Mais comme il n'y a pas de persistance de ce code d'un programme à l'autre, ce n'est pas un système d'exploitation.
la source
Je pense que beaucoup de réponses méconnaissent la question, qui se résume à ceci:
Fondamentalement, la CPU exécute directement le code machine . Il serait beaucoup plus lent que le noyau exécute toutes les applications. Cependant, il y a quelques mises en garde.
Lorsqu'un système d'exploitation est présent, les programmes d'application ne peuvent généralement pas exécuter certaines instructions ou accéder à certaines ressources. Par exemple, si une application exécute une instruction qui modifie la table d’interruption du système, la CPU passe à la place à un gestionnaire d’exceptions du système d’exploitation de sorte que l’application incriminée soit terminée. De plus, les applications ne sont généralement pas autorisées à lire / écrire dans la mémoire de l'appareil. (Par exemple, "parler au matériel".) L'accès à ces régions de mémoire spéciales permet au système d'exploitation de communiquer avec des périphériques tels que la carte graphique, l'interface réseau, l'horloge système, etc.
Les restrictions imposées par un système d'exploitation aux applications sont obtenues grâce à des fonctionnalités spéciales de la CPU, telles que les modes de privilège, la protection de la mémoire et les interruptions. Bien que tous les processeurs présents sur un smartphone ou un PC possèdent ces fonctionnalités, certains ne le font pas. Ces processeurs ont en effet besoin de noyaux spéciaux qui "interprètent" le code de l'application afin d'obtenir les fonctionnalités souhaitées. Un exemple très intéressant est le Gigatron , un ordinateur à 8 instructions que vous pouvez construire à partir de puces qui émulent un ordinateur à 34 instructions.
Certains langages comme Java "compilent" quelque chose appelé Bytecode, qui n'est pas vraiment du code machine. Bien que, dans le passé, ils étaient interprétés pour exécuter les programmes, de nos jours, on utilise généralement la compilation Just-in-Time, qui s'exécute donc directement sur le processeur en tant que code machine.
L'exécution d'un logiciel dans une machine virtuelle exigeait que son code machine soit "interprété" par un programme appelé hyperviseur . En raison de la forte demande de machines virtuelles du secteur, les fabricants de processeurs ont ajouté des fonctionnalités telles que VTx à leurs processeurs pour permettre à la plupart des instructions d'un système invité d'être exécutées directement par le processeur. Toutefois, lorsque vous exécutez un logiciel conçu pour un processeur incompatible dans une machine virtuelle (par exemple, en émulant un NES), le code de la machine devra être interprété.
la source
Lorsque vous compilez votre code, vous créez un code dit "objet" qui (dans la plupart des cas) dépend des bibliothèques système (
printf
par exemple), puis votre code est encapsulé par un éditeur de liens qui ajoutera un type de chargeur de programme que votre système d'exploitation particulier peut reconnaissez (c’est pourquoi vous ne pouvez pas exécuter de programme compilé pour Windows sous Linux, par exemple) et savez comment décompresser votre code et l’exécuter. Votre programme se présente donc comme une viande dans un sandwich et ne peut être consommé que dans un paquet.Eh bien, c'est à moitié vrai; si votre programme est un pilote en mode noyau, vous pouvez accéder directement au matériel si vous savez "parler" avec ce dernier, mais généralement (surtout pour du matériel non documenté ou compliqué), les pilotes utilisent des pilotes qui sont des bibliothèques du noyau. De cette façon, vous pouvez trouver des fonctions d'API qui savent comment parler au matériel de manière lisible par l'homme sans avoir besoin de connaître les adresses, les registres, le minutage et bien d'autres choses encore.
Eh bien, le noyau est en tant que serveuse, dont la responsabilité est de vous accompagner à une table et de vous servir. La seule chose que cela ne puisse pas faire, c’est manger pour vous, vous devriez le faire vous-même. De même avec votre code, le noyau décompactera votre programme dans une mémoire et démarrera votre code qui est un code machine exécuté directement par la CPU. Un noyau a juste besoin de vous superviser - ce qui vous est permis et ce que vous n'êtes pas autorisé à faire.
Le code machine généré après la compilation est une instruction adressée directement à la CPU. Aucun doute là-dessus. La seule chose que vous devez garder à l'esprit, tous les codes d'un fichier compilé ne sont pas le code de la machine / du processeur. Linker a enveloppé votre programme avec des métadonnées que seul le noyau peut interpréter, en guise d’indice - que faire avec votre programme.
Si votre code est juste des opcodes simples comme l’ajout de deux registres, il sera exécuté directement par la CPU sans assistance du noyau, mais si votre code utilisant des fonctions de bibliothèques, ces appels sont assistés par le noyau, comme dans l’exemple avec la serveuse, si vous le souhaitez. pour manger dans un restaurant, ils vous donneraient des outils - une fourchette, une cuillère (et cela reste leurs atouts), mais ce que vous allez en faire - dépend de votre "code".
Bien, juste pour éviter les flammes dans les commentaires - c'est un modèle vraiment simpliste que j'espère aiderait OP à comprendre les choses de base, mais de bonnes suggestions pour améliorer cette réponse sont les bienvenues.
la source
Essentiellement, seuls les appels système vont au noyau. Tout ce qui concerne les E / S ou l’allocation / désallocation mémoire entraîne généralement un appel système. Certaines instructions ne peuvent être exécutées qu'en mode noyau et le processeur déclenchera une exception. Les exceptions entraînent le passage au mode noyau et le passage au code du noyau.
Le noyau ne traite pas toutes les instructions d'un programme. Il ne fait que les appels système et bascule entre les programmes en cours pour partager le processeur.
Il est impossible d'allouer de la mémoire en mode utilisateur (sans le noyau). Si vous accédez à une mémoire à laquelle vous n'êtes pas autorisé, le MMU, préalablement programmé par le noyau, remarque et provoque une exception "erreur de segmentation" au niveau de la CPU. , qui déclenche le noyau et le noyau tue le programme.
Effectuer des E / S en mode utilisateur (sans le noyau) n’est pas possible. Si vous accédez à des ports d’E / S ou à des registres pour des périphériques, ou à des adresses connectées à des périphériques exception de la même manière.
Dépend du type d'exécutable.
Les noyaux, en plus d'assurer la médiation de l'accès partagé à la RAM et au matériel, remplissent également une fonction de chargeur.
De nombreux "formats exécutables", tels que ELF ou PE, contiennent des métadonnées dans le fichier exécutable en plus du code et le travail du chargeur pour le traiter. Lisez les détails sanglants sur le format PE de Microsoft pour plus d'informations.
Ces exécutables font également référence à des bibliothèques ( fichiers d’
.dll
objets partagés Windows ou Linux.so
) - leur code doit être inclus.Si votre compilateur produit un fichier destiné à être traité par un chargeur de système d'exploitation et que ce dernier n'est pas présent, cela ne fonctionnera pas.
Sûr. Vous devez convaincre le système d'exploitation de faire fonctionner votre code brut d'une manière ou d'une autre sans traiter aucune métadonnée. Si votre code appelle les API du noyau, cela ne fonctionnera toujours pas.
Si vous chargez cet exécutable à partir d'un système d'exploitation (c'est-à-dire s'il permet le chargement et l'exécution de code brut), il sera toujours en mode utilisateur. Si votre code accède à des choses interdites en mode utilisateur, par opposition au mode noyau, telles que la mémoire non allouée ou les adresses / registres de périphériques d'E / S, il se plantera avec des violations de privilège ou de segment (là encore, les exceptions passent en mode noyau et sont traitées là) et ne fonctionne toujours pas.
Alors ça va marcher.
la source
TL; DR Non.
Le développement Arduino vient à l’esprit comme un environnement actuel où il n’ya pas de système d’exploitation. Croyez-moi, sur l'un de ces bébés, vous n'avez pas de place pour un système d'exploitation.
De même, les jeux pour Sega Genesis n’avaient pas d’OS fourni par Sega. Vous venez de concevoir votre jeu en assembleur 68K, en écrivant directement sur du métal nu.
Ou je me suis fait les dents en faisant du travail intégré sur le processeur Intel 8051. Encore une fois, lorsque vous n’avez qu’un Eprom 2716 avec un encombrement de 2 * 8, vous n’avez pas la place pour un système d’exploitation.
Bien entendu, cela suppose une utilisation très large du mot application. En guise de question rhétorique, il convient de se demander si une esquisse Arduino est réellement une application.
la source
Bien que je ne veuille pas laisser entendre que les autres réponses ne sont pas correctes en elles-mêmes, elles fournissent beaucoup trop de détails qui, je le crains, sont encore très obscurs pour vous.
La réponse de base est que le code sera exécuté directement sur le processeur. Et non, le code machine ne "parlera" à personne, c'est l'inverse. Le processeur est le composant actif et tout ce que vous faites dans votre ordinateur sera fait par ce processeur (je simplifie un peu les choses ici mais c'est OK pour le moment). Le processeur lira le code, l'exécutera et crachera les résultats. Le code machine servira de nourriture au processeur.
Votre confusion provient de l'utilisation du mot hardware. Bien que la division ne soit plus aussi claire qu’elle était, il est préférable de penser en termes de périphériques plutôt que d’appeler simplement tout le matériel. Ainsi, s'il existe un système d'exploitation ou similaire sur votre machine, votre programme doit utiliser ses services pour accéder aux périphériques mais le processeur lui-même n'est pas un périphérique, c'est l'unité de traitement principale sur laquelle votre programme s'exécute directement.
Les noyaux, les systèmes d’exploitation et les couches intermédiaires similaires ne sont généralement utilisés que dans des systèmes plus grands où plusieurs programmes sont exécutés et où le système doit gérer la manière dont ces programmes peuvent utiliser les périphériques de l’ordinateur (assez souvent à la machine). en même temps). Dans ces cas, les programmes en cours ne peuvent accéder à ces périphériques qu'en utilisant le système qui décidera de la manière de les partager et s'assurera qu'il n'y a pas de conflits. Les petits systèmes ne nécessitant aucune gestion parmi les programmes concurrents, car aucun n’est, n’ont souvent aucun système sous-jacent et le programme unique fonctionnant normalement sur ces systèmes est plus ou moins libre de faire ce qu’il veut avec les périphériques.
la source
Le BIOS qui s'exécute sur votre ordinateur à la mise sous tension est un code exécutable stocké dans la ROM. Il se compose d'instructions machine et de données. Il existe un compilateur (ou un assembleur) qui assemble ce BIOS à partir du code source. C'est un cas particulier.
D'autres cas spéciaux incluent le programme d'amorçage qui charge le noyau et le noyau lui-même. Ces cas spéciaux sont généralement codés dans un langage autre que C ++.
Dans le cas général, il est beaucoup plus pratique de demander au compilateur de produire des instructions qui appellent des services système fournis par un noyau ou par des routines de bibliothèques. Cela rend le compilateur beaucoup plus léger. Cela rend également le code compilé plus léger.
Java est à l'autre bout du spectre. En Java, le compilateur ne traduit pas le code source en instructions machine, ce terme étant généralement compris. Au lieu de cela, le code source est traduit en "instructions machine" pour une machine imaginaire appelée machine virtuelle Java. Avant de pouvoir exécuter un programme Java, il doit être associé à l'environnement d'exécution Java, qui comprend un interpréteur pour la machine virtuelle Java.
la source
Dans le bon vieux temps, votre programme était chargé de faire tout ce qui devait être fait pendant son exécution, soit en le faisant vous-même, soit en ajoutant du code de bibliothèque que d'autres personnes avaient écrit dans votre programme. La seule chose qui se passait à côté de cela dans l'ordinateur était le code à lire dans votre programme compilé - si vous aviez de la chance. Certains ordinateurs devaient avoir un code entré via des commutateurs avant de pouvoir en faire plus (le processus "d'amorçage" d'origine), ou même votre programme entier entré de cette façon.
Nous avons rapidement constaté qu’il était agréable d’avoir du code capable de charger et d’exécuter un programme. Plus tard, il s’est avéré que les ordinateurs étaient assez puissants pour supporter l’exécution simultanée de plusieurs programmes en faisant basculer le processeur entre eux, en particulier si le matériel pouvait y contribuer, , comment gérer plusieurs programmes essayant d’envoyer simultanément des données à l’imprimante?).
Tout cela a eu pour effet qu'une grande quantité de code d'assistance a été déplacée des programmes individuels vers le "système d'exploitation", avec un moyen normalisé d'invoquer le code d'assistance à partir de programmes utilisateur.
Et c'est là où nous en sommes aujourd'hui. Vos programmes fonctionnent à plein régime, mais chaque fois qu’ils ont besoin de quelque chose géré par le système d’exploitation, ils appellent des routines d’aide fournies par le système d’exploitation. Ce code n’est ni nécessaire ni présent dans les programmes utilisateurs eux-mêmes. Cela comprenait l’écriture sur l’affichage, la sauvegarde de fichiers, l’accès au réseau, etc.
Des micro-noyaux ont été écrits pour fournir exactement ce qui est nécessaire à un programme donné pour s'exécuter sans système d'exploitation complet. Cela présente certains avantages pour les utilisateurs expérimentés tout en abandonnant la plupart des autres. Vous voudrez peut-être lire la page Wikipedia à ce sujet - https://en.wikipedia.org/wiki/Microkernel - si vous voulez en savoir plus.
J'ai expérimenté un micro-noyau capable d'exécuter une machine virtuelle Java, mais j'ai découvert plus tard que la solution idéale pour cela est Docker.
la source
Dans les systèmes d’exploitation de bureau classiques, le noyau lui - même est un exécutable. (Windows a
ntoskrnl.exe
; Linux avmlinux
, etc.) Si vous aviez besoin d'un noyau pour qu'un exécutable puisse s'exécuter, alors ces systèmes d'exploitation ne pourraient pas exister.Ce dont vous avez besoin d’un noyau, c’est de faire ce que fait un noyau. Autoriser l'exécution simultanée de plusieurs exécutables, arbitrer entre eux, résumer le matériel, etc. La plupart des programmes ne sont pas capables de le faire eux-mêmes avec compétence, et vous ne voudriez pas qu'ils le fassent même s'ils le pouvaient. À l'époque du DOS - que l'on pouvait à peine appeler un système d'exploitation lui-même -, les jeux utilisaient souvent le système d'exploitation un peu plus qu'un chargeur, et accédaient directement au matériel, à la manière d'un noyau. Mais avant d'acheter un jeu, vous deviez souvent savoir quelles marques et quels modèles de matériel se trouvaient sur votre machine. De nombreux jeux ne prenaient en charge que certaines familles de cartes son et vidéo, et fonctionnaient très mal sur les marques concurrentes si elles fonctionnaient du tout. Cette'
la source