choper les stackoverflow sous morphos/gcc

5 sujets de 31 à 35 (sur un total de 35)

  • kakace

      #28947

      krabob a écrit :

      Hier soir j’ai pris vingt minutes pour parcourir exec.doc et ses .h Et je trouve que des choses évidentes apparaissent.

      Rappel: exec a du être fait vers 1985 par sassenrath et à cette époque UNIX avait dejà la mémoire protégée. de plus

      il est evident qu’amigaOS s’inspire d’UNIX dans son noyau. en 85, les 68000 n’avaient pas de MMU. il était évident que les 68000 évolueraient vers du MMU.

      Je confirme qu’Exec pose les bases d’un tel système, du moins depuis le Workbench 2.0 (si ma mémoire est bonne, c’est à cette époque qu’est apparu le symbole MEMF_PUBLIC et les conseils d’utilisations associés). Néanmoins, la documentation liée à Exec (notament le RKRM) persiste à autoriser certaines choses incompatibles avec la protection mémoire. Je n’ai plus d’exemple précis en tête (ni les docs pour en retrouver), mais la simple présence des macros Forbid, Permit, Disable et Enable, entre autres, met en évidence le manque de rigueur. Ces macros suggèrent que la mémoire utilisée par l’exec.library doit être accessible par tout le monde, donc non protégée.

      J’admets que l’exemple est simpliste, faute de mieux. S’il existe des fonctions encapsulant ces fonctionalités, il n’en demeure pas moins que des macros, documentées, permettent de s’en affranchir.

      Partout on a la notion de “fabrique” (au sens des design pattern, gestionnaire encapsulé qui crée et détruit des objet.) comme dans un systeme protégé. Par exemple, pour créer un écran, tu donnes à OpenScreen() une description (taglist) privée, et on te renvoie un pointeur vers une mémoire publique, dont la logique

      est d’etre en lecture seule pour la tâche. et on a une fonction de destruction: CloseScreen()

      La notion de “fabrique” vient des systèmes orientés objets, et permet l’abstraction nécessaire à l’évolution sans douleur de l’OS (modification de l’objet fabriqué). L’exemple d’OpenScreen() me ramène au paragraphe précédent : IIRC, OpenScreen() demande une structure NewScreen, laquelle contient bon nombre de pointeurs vers différentes choses, dont une taglist optionnelle. Via cette fonction, on demande donc à l’intuition.library de construire un “écran” à partir de données réputés privées (celles adressées par ces pointeurs). A moins de décréter que ces objets doivent être alloués dans une zone publique, ce qui exclu d’office les objets statiques.

      Le terme de mémoire publique signifie que les données sont accessibles par plusieurs tâches sans gestion particulière. Cela ne veut pas nécessairement dire que ces données sont seulement accessibles en lecture.

      Je me suis interessé aux messages que tu dis si sensible: dans exec, on a CreateMsgPort() et DeleteMsgPort() pour créer des ports de gestion de message. On manipule juste leurs pointeurs: gestion encapsulé en public,et justement

      les messages pointent ces ports. Et exec.doc nous met en garde de pas bricoler son port soit meme,comme par hazard.

      Certe, mais un message ne contient généralement pas que cette structure. Il est souvent utilisé pour transmettre des données à une autre tâche, et ce sont ces données annexe qui posent un problème lorsqu’elles comportent des pointeurs (et ça, l’OS ne peut pas le deviner). Si on veut être certain que la tâche destinataire soit capable de récupérer l’ensemble des données, il faut tout mettre en mémoire publique (à défaut d’avoir un système autrement plus compliqué et capable de gérer ça tout seul grace à de vrais objets, au sens OO du terme).

      Je me suis ensuite interessé a PutMsg() qui permet d’envoyer des messages alloués sois-meme en privée, donc qui

      pourrait poser probléme. Je me suis d’abord aperçu qu’en 6 ans de prog systeme je ne l’ai jamais utilisé !

      Il n’empêche que cette fonction est documentée, donc parfaitement utilisable. C’est le cas d’autres fonctions (les exemples ne manquent pas), et c’est l’un des aspects qui m’a fait dire qu’il fallait revoir en profondeur tout l’OS pour éliminer les fonctions incompatibles avec la mémoire protéger, revoir la documentation, etc.

      Mais voilà, dans cette struct il faut forcément remplir nm_Length,

      qui contient la taille de la structure. Cela permet potentiellement à l’OS de la copier vers une struct publique a l’execution de PutMsg().

      D’accord, mais le système reste “bancal”. On ne peut pas effacer PutMsg() d’un coup de baguette magique (c’est toujours documenté), et ça ne résoud pas le problème des pointeurs contenus dans l’objet transféré par message. Le problème basique des pointeurs contenus dans des objets est soulevé dans toutes les docs traitant des systèmes orientés objets, d’où la nécessité des constructeurs de recopie en C++ par exemple. Ce type de constructeur n’existe pas au niveau des API.

      Pourquoi les concepteurs amiga aurait spécifié de remplir ce champs depuis 1985 alors qu’il est inutile dans une contexte non protégé ? Parce qu’ils avaient prévu de basculer tout amigaOS en protection mémoire c’est évident. Tout les exemple utilisant PutMsg remplissent ce champ.

      Je ne dis pas le contraire. Exec est certainement la partie la plus aboutie dans ce domaine, même si ce n’est pas suffisant. Sassenrah a débrousaillé le terrain, mais il reste beaucoup à (re-)faire y compris dans Exec.

      Le problème principal est que ce système (recopier des msg) impose d’incessantes recopies de données lors

      des communications entre tâches et accessoirement entre une tâche et l’OS (si nécessaire). C’est synonyme de ralentissement au niveau des API de communication inter-processus, et c’est la raison principale qui fait que l’AmigaOS et ses dérivés sont plus réactifs que les OS “protégés”

      je ne suis pas d’accord du tout, tu résonnes en 68000,un cpu sans cache, ou meme le code executé devait passer systematiquement par le bus lors de l’execution, ou la moindre lecture/ecriture passait du cpu a la ram. Si les autres OS ne sont pas réactif, c’est à cause de leurs politiques de memoire virtuelle qui va meme cacher de la memoire video, avec des notions de priorité pas applicables (windows).

      Heu… Je ne vois pas le rapport, étant donné que les caches n’ont rien à voir là-dedans pour la simple et bonne raison qu’on ne peut pas garantir que les données soient dans toujours dans le cache quand on en a besoin (une bête interruption au mauvais moment peut changer la donne radicalement).

      Dans le cas de recopie de message: On a UNE SEULE COPIE DE STRUCTURE PAR CREATION DE MESSAGE vers une mem publique, pas plus !!, et ces structs sont de taille minimale ! le PowerPC quand il switche de contexte de tache ( un nombre important de fois par seconde,meme sans protection) doit empiler/depiler 384 octet de regsitres, et au moins la moitié a chaque saut de fonctions !!

      ainsi Les flux mémoires du au simple fonctionnement du PPC sont énormément plus volumineux et fréquent qu’une copie de struct de temps en temps.

      Je n’ai pas quantifié l’impact. Le fait est qu’avoir des opérations supplémentaires induit obligatoirement un ralentissement. En dehors de ça, tout est question d’argumentation, pour ne pas dire de polémique.

      Les implications d’une protection mémoire vont bien au delà de ce simple problème de recopie.

      et considérez ceci:

      dans un systeme non protégé PowerPC, la lecture d’une struct en cache prend un certain temps (lecture).

      La recopie de la méme struct vers une plage publique peut se faire avec dcbz (en interne): dans ce cas, la copie

      prend PRESQUE AUTANT de temps que la lecture seule de la struct du message !!!

      Oui, si on considère que cette structure est toujours dans le cache au moment où on en a besoin. Sinon, il faut la récupérer en RAM, et c’est BEAUCOUP plus lent.

      La protection mémoire n’est pas l’ennemie de la réactivité !!! faut arreter de penser 68000 !!! La protection mémoire sous AMigaOS est possible et on l’aura !

      Elle n’est pas l’ennemie de la réactivité, mais elle réduit nécessairement cette réactivité dans des proportions qui restent à déterminer. Tout dépend de quel niveau de protection on parle, et comment cette protection est globalement implémentée au niveau de l’OS.

      En l’état actuel des choses, un embryon de système pourrait éventuellement être implémenté en ayant recours massivement à la mémoire publique (donc non protégée). Efficacité mitigée garantie puisque beaucoup de choses seraient alors accessibles par beaucoup de tâches différentes.

      Pour une vraie protection, il faudrait impérativement débarrasser les APIs de toutes les fonctions posant un problème de fond (utilisation d’objets contenant des pointeurs vers d’autres objets), revoir la documentation pour en expurger la totalité des passe-droits (accès directs à certains membres) et donc ajouter des “accesseurs”. Il faudrait aussi se diriger vers une approche OO plus poussée, notament pour proposer des constructeurs de recopie adaptés. Il faudrait préciser les notions de propriété et de responsabilité envers les objets manipulés. Il faudrait revoir le principe des bibliothèques partagées (actuellement en mémoire publique), des “devices” et autres “handlers” pour les protéger des applications (faute de quoi n’importe quelle tâche peut faire écrouler l’OS). En bref, un énorme travail de fond lequel ne peut pas se faire sans casser des oeufs (compatibilité).

      Au final, un tel OS serait tellement différent, avec des règles plus strictes et une nouvelle façon de programmer, qu’il n’aurait probablement qu’un rapport assez éloigné avec l’OS actuel (même s’il est possible d’en garder l’esprit).

      Lanza

        #28948

        La notion de “fabrique” vient des systèmes orientés objets, et permet l’abstraction nécessaire à l’évolution sans douleur de l’OS (modification de l’objet fabriqué). L’exemple d’OpenScreen() me ramène au paragraphe précédent : IIRC, OpenScreen() demande une structure NewScreen, laquelle contient bon nombre de pointeurs vers différentes choses, dont une taglist optionnelle. Via cette fonction, on demande donc à l’intuition.library de construire un “écran” à partir de données réputés privées (celles adressées par ces pointeurs). A moins de décréter que ces objets doivent être alloués dans une zone publique, ce qui exclu d’office les objets statiques.

        Le terme de mémoire publique signifie que les données sont accessibles par plusieurs tâches sans gestion particulière. Cela ne veut pas nécessairement dire que ces données sont seulement accessibles en lecture.

        Heuu, quand tu appelles une fonction Intuition telle qu’OpenScreen(), même si le code est celui de la lib, la tâche en cours reste la tienne et a donc accès à ses données privées. Libre ensuite à OpenScreen() d’en faire une copie en espace public pour les passer aux tâches du système. Ce qui est d’ailleurs plus ou moins déjà fait puisqu’elle te retourne une struct screen allouée par ses soins.

        Je n’ai pas d’objections au reste du message. :-)

        Yomgui

          #28949

          De toute façon quand on code proprement la mémoire protégée ça sert à rien!

          na !

          :p :p :p :p

          Lanza

            #28950

            Heuu, ça peut servir à empêcher des méchants programmes écrits par de vilains hackers, de faire planter ta machine, de récupérer des infos privées, etc.

            C’est clair que vu la représentation de l’amiga sur la marché informatique, on est moins exposés à ce genre de méchants programmes, mais bon.

            kakace

              #28951

              Lanza a écrit :

              Heuu, quand tu appelles une fonction Intuition telle qu’OpenScreen(), même si le code est celui de la lib, la tâche en cours reste la tienne et a donc accès à ses données privées. Libre ensuite à OpenScreen() d’en faire une copie en espace public pour les passer aux tâches du système. Ce qui est d’ailleurs plus ou moins déjà fait puisqu’elle te retourne une struct screen allouée par ses soins.

              D’accord, mais cela ne résoud en rien le fait que la copie doit pouvoir prendre en compte les nombreux pointeurs vers d’autres objets (le problème général étant ces pointeurs). D’autre part, en l’état actuel des choses, le code de la bibliothèque (et accessoirement les données “privées” de celle-ci) est accessible par n’importe quelle tâche, ce qui remet en cause la protection de cette bibliothèque, et donc celle de l’OS au sens large.

              La difficulté n’est pas de trouver une parade à un problème précis. Elle est de trouver une parade qui ne remet pas en cause les solutions apportées à d’autres problèmes, ce qui nécessite d’avoir une vision plus globale du système. Ainsi, si on veut vraiment protéger l’OS, il faut commencer par isoler les bibliothèques du contexte des tâches, faute de quoi la perte d’une bibliothèque entraîne les autres tâches clientes et l’OS dans sa chute. A partir de là, les solutions disponibles pour transmettre les informations entre différents contextes sont passablement réduites. Abuser de la mémoire publique remet en cause la protection d’un point de vue global, et ce n’est pas (à mon avis) la bonne solution. Il ne reste donc que la copie intégrale (dans la plupart des cas), laquelle est actuellement difficilement réalisable à cause des nombreux pointeurs qui “polluent” les différents objets manipulés, lesquels ne disposent pas de “constructeurs de recopie” susceptibles d’effectuer cette opération. D’autre part, la séparation des contextes impose d’avoir de nombreux accesseurs pour lire ou modifier des données “étrangères”.

              Maintenant, tout dépend du but recherché. S’il est possible d’avoir une protection minimaliste sans trop d’efforts, une vraie protection n’est pas réalisable sans devoir changer tout un tas de choses. Et quand je dis protection minimaliste, je suis gentil…

            5 sujets de 31 à 35 (sur un total de 35)

            • Vous devez être connecté pour répondre à ce sujet.

            Forums AmigaOS, MorphOS et AROS Développement choper les stackoverflow sous morphos/gcc

            Amiga Impact