IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

 C Discussion :

simulation système RAID5


Sujet :

C

  1. #1
    Membre éprouvé
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Août 2011
    Messages
    756
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 31
    Localisation : France, Haute Garonne (Midi Pyrénées)

    Informations professionnelles :
    Activité : Ingénieur développement logiciels

    Informations forums :
    Inscription : Août 2011
    Messages : 756
    Par défaut simulation système RAID5
    Bonjour/Bonsoir à tous;

    je viens vous demander un petit coup de main dans le cadre d'un projets que je dois réaliser pour la fin des vacances; ce n'est pas dans au niveau du codage (ça je sais que je vais galérer mais ça fait partie du jeu ) mais surtout de la compréhension du sujet qui est je dois le dire un peu "hard".

    Grosso modo le but du projet est de développer l'ensemble des fonctions qui ferait tourner un système RAID5; sauf qu'ici pour simplifier notre problèmes; au lieu de travailler sur 4 disques, l'on symbolise ces disques par 4 fichiers d0 d1 d2 d3 chacun de même taille.

    J'ai pu voir divers résumé de comment fonctionnent ces système RAID5
    Notamment ici: http://fr.wikipedia.org/wiki/RAID_(i...tique)#RAID_05

    Mais j'avoue avoir un peu de mal à faire une synthèse par rapport à ce que l'on me demande.

    En fait, j'aimerais être sur d'avoir bien compris les notions:

    - de bloc de données
    - bloc de parité
    - bande
    - table d'inode


    Pour "débuter" ce projet; un certains nombres de structures nous est déjà fournies.

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    #ifndef __R5_DEFINES__
    #define __R5_DEFINES__
     
    #define NUMBER_OF_DISKS 4
    #define BLOCK_SIZE 4
    #define FILENAME_MAX_SIZE 32
    #define MAX_FILES 100
    #define MAX_FILE_SIZE (50*1024)
     
     
    typedef unsigned int uint;
    typedef unsigned char uchar;
     
    /* Type of a block of data */
    typedef struct block_s{
        uchar data[BLOCK_SIZE];
    } block_t;
     
    /* Type of the pseudo-inode structure */
    typedef struct inode_s{
      char filename[FILENAME_MAX_SIZE];
      uint size;
      uint nblock; // nblock = (size+BLOCK_SIZE-1)/BLOCK_SIZE
      uint block_id;
    } inode_t;
     
    /* Type of the inode table */
    typedef inode_t inode_table_t[MAX_FILES];
     
    /* Type of the virtual disk system */
    typedef struct virtual_disk_s {
        inode_table_t inodes;
        int ndisk;
        int raidmode;
        FILE *storage[NUMBER_OF_DISKS];
    } virtual_disk_t;
    Ce que je voudrais avoir bien compris avant de débuter un quelconque codage hasardeux c'est le rapport entre les structures virtual_disk et inodes par rapport au travail qui doit être fait.


    Simple exemple de mon incompréhension du sujet; ma première tâche est d'écrire une fonction qui initialiserait une variable globale "virtual disk_t g_disk ;" à partir du nom de répertoire contenant les disques virtuel. (On n'initialise pas la table d'inode dans un premier temps).
    Mais pour le reste; je ne comprends pas vraiment à quoi correspondent les variables dans la structures.

    Le fait d'allumer et d'éteindre le système RAID5 correspond il au fait d'ouvrir et de fermer les fichiers ?


    Voilà désolé pour la masse de questions

    Merci d'avance pour votre aide quand à la compréhension de ce sujet !

  2. #2
    Membre Expert
    Avatar de Metalman
    Homme Profil pro
    Enseignant-Chercheur
    Inscrit en
    Juin 2005
    Messages
    1 049
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 36
    Localisation : France, Hauts de Seine (Île de France)

    Informations professionnelles :
    Activité : Enseignant-Chercheur
    Secteur : Enseignement

    Informations forums :
    Inscription : Juin 2005
    Messages : 1 049
    Par défaut
    1) Tu veux bien faire du RAID5 "normal"/simple ?
    Parce que tu nous envoie sur le 05 !

    2) Tu veux faire du RAID5... mais... dans le sens "hardware" ou "software" ?
    Hard => disques qui offrent une visibilité d'espace "normal", mais qui derrière font des bandes redondées
    Soft => les disques sont normaux... ce sont les partitions qui sont dupliquées un peu partout... et là c'est le bordel à implémenter.... parce que tu as à la fois la gestion du FS à faire + la gestion du RAID sur plusieurs disques

    Si tu arrives déjà à simuler du RAID5 hardware dans tes 4 fichiers, ça sera un premier pas très important pour toi !
    --
    Metalman !

    Attendez 5 mins après mes posts... les EDIT vont vite avec moi...
    Les flags de la vie : gcc -W -Wall -Werror -ansi -pedantic mes_sources.c
    gcc -Wall -Wextra -Werror -std=c99 -pedantic mes_sources.c
    (ANSI retire quelques fonctions comme strdup...)
    L'outil de la vie : valgrind --show-reachable=yes --leak-check=full ./mon_programme
    Et s'assurer que la logique est bonne "aussi" !

    Ma page Developpez.net

  3. #3
    Membre éprouvé
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Août 2011
    Messages
    756
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 31
    Localisation : France, Haute Garonne (Midi Pyrénées)

    Informations professionnelles :
    Activité : Ingénieur développement logiciels

    Informations forums :
    Inscription : Août 2011
    Messages : 756
    Par défaut
    Je pense que c'est bien le RAID5 "simple"

    Celui qui correspond à ce schéma:



    Et oui je pense que je serais assez content si j'arrivais à le faire

    Pour ta question 2; je saurais pas trop te dire; le projet simule les disques avec des fichiers et la perte de données par la suppression de l'un des fichiers. En tout cas c’est ce qu'il me semble en avoir compris.

  4. #4
    Membre Expert
    Avatar de Metalman
    Homme Profil pro
    Enseignant-Chercheur
    Inscrit en
    Juin 2005
    Messages
    1 049
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 36
    Localisation : France, Hauts de Seine (Île de France)

    Informations professionnelles :
    Activité : Enseignant-Chercheur
    Secteur : Enseignement

    Informations forums :
    Inscription : Juin 2005
    Messages : 1 049
    Par défaut
    On t'a donné le sujet et il y a une moulinette de correction automatique qui donne des fichiers avec un format précis ?

    Ou c'est bien un projet à présenter ?

    Si tu restes dans le projet à présenter... il te faut quelques specs avant...
    Par exemple : la taille max des fichiers... elle représentera la taille de chaque disque

    - Tu peux démarrer en faisant une fonction qui coupera en bandes de taille N chaque fichier (CAD, tu prépares une structure qui décrit la taille des bandes, et numérote chaque fichier)
    - Ensuite, tu peux faire une écriture "simple" : tu donnes un texte d'une certaine taille, et il va être découpé sur chaque bande (il faut un gros texte OU des petites bandes pour passer correctement ce test)... si tes bandes sont suffisament petites, en faisant un "cat" de chaque fichier, tu verras ton texte dans les 3 premiers fichiers, et le résultat du XOR dans le 4e
    - La lecture, cette fois tu demandes à lire N octets de tes disques, et ça va lire dans "le bon ordre" chaque bande (c'est pour cela que tu dois garder dans ta structure initiale un nombre fixe par fichier/disque pour savoir dans quel ordre les itérer en lecture quand tu dépasses la taille d'une bande)
    - Lecture "en mode récup'", cette fois tu as perdu un fichier, et tu fais la reconstruction du disque manquant en faisant les XOR des disques manquant

    Si tu as ça... tu auras la "base"...
    Il ne te manquera plus qu'une fonction de reconstruction qui sera "en gros" une surcouche de la lecture en mode récup' sur la taille d'un disque


    EDIT : ah oui mal lu que tu as un header forcé ! désolé.
    --
    Metalman !

    Attendez 5 mins après mes posts... les EDIT vont vite avec moi...
    Les flags de la vie : gcc -W -Wall -Werror -ansi -pedantic mes_sources.c
    gcc -Wall -Wextra -Werror -std=c99 -pedantic mes_sources.c
    (ANSI retire quelques fonctions comme strdup...)
    L'outil de la vie : valgrind --show-reachable=yes --leak-check=full ./mon_programme
    Et s'assurer que la logique est bonne "aussi" !

    Ma page Developpez.net

  5. #5
    Membre éprouvé
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Août 2011
    Messages
    756
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 31
    Localisation : France, Haute Garonne (Midi Pyrénées)

    Informations professionnelles :
    Activité : Ingénieur développement logiciels

    Informations forums :
    Inscription : Août 2011
    Messages : 756
    Par défaut
    On me fournit un début de spec avec le header que j'ai mis un peu plus haut.
    Les 4 fichiers (représentant les disques) sont générés par un script et ont par conséquent tous la même taille et seront contenus dans un même dossier.

    J'ai tout un tas de fonctions et procédures à faires ce n'est donc pas un projet où on est libre de présenter les choses comme on veut, je dois respecter ce que l'on me demande de faire.

    J'aimerais bien faire passer le pdf en pièce jointe mais avec ma connexion je plante chaque fois avant de l'avoir uploader en entier... peut être par mail aurais je plus de chance ? Mais je veux pas abuser non plus

    Le projet est découpé en 3 parties

    1 Gestion du RAID de bas niveau
    2 Gestion e la table d'inode
    3 Lecture/Ecriture/Suppression de fichiers.




    Pour mon projet la taille des 4 fichiers est fixé à 500 000 octet Soit 500 Mo

    Mais; si ça t'embête pas, ce que je cherche à faire ce serait un exemple simple et concret (même si ce n'est pas réaliste) en fixant une taille infime

    Imaginons 4 fichiers de taille 20 octet.
    Un bloc aurait une taille arbitraire de 3 octet.

    Comment va se faire le découpage sur cet exemple lorsque l'on écrira dans le fichier ?

  6. #6
    Membre Expert
    Avatar de Metalman
    Homme Profil pro
    Enseignant-Chercheur
    Inscrit en
    Juin 2005
    Messages
    1 049
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 36
    Localisation : France, Hauts de Seine (Île de France)

    Informations professionnelles :
    Activité : Enseignant-Chercheur
    Secteur : Enseignement

    Informations forums :
    Inscription : Juin 2005
    Messages : 1 049
    Par défaut
    Oui j'avais mal lu ton premier post... omg... pardon...

    Pour le RAID5 de "base" sans penser aux inodes, mais juste en termes de données, voilà ce qui se passera :

    1) 4 disques de 20o chacun = 3 disques utilisables, et 1 de redondance
    CAD : 3 * 20 = 60o utilisables

    2) Les blocs font 3o... c'est... pas génial... mais bon...
    20 / 3 = 6o
    Donc on va avoir 6 blocs de 3o sur chaque disque...
    Donc en effet 6 bandes de 9o utilisables + 3o de redondance
    3 * 6 = 18, 20 - 18 = 2o
    Et pour ne rien perdre : 1 bloc supplémentaire de 2o
    (il vaut mieux perdre cet espace pour le moment... et ne pas s'en soucier)

    3) Tu vas vouloir écrire 10o par exemple... (ça va dépasser... mais osef)
    10 / 3 = 3
    3 * 3 = 9
    9 != 10
    3 blocs ne suffisent pas, il en faudra un 4e...
    Donc on va consommer 4 blocs. (sur le schéma wikipedia on va donc réserver les blocs A1, A2, A3 et B1... et on va écrire sur A1-3 & Ap et B1 et Bp)

    B1 étant "seul".... pour faire une redondance, il faudra connaitre les valeurs des autres bandes B !
    Pour cela, il faut initialiser les bandes !
    Donc avant toute chose, pour que le RAID soit dispo, il faut l'initialiser en le remplissant de '\0' (sur TOUTES les bandes).

    4) Tu vas écrire 0123456789 (10 caractères) sur ton RAID, on a dit qu'il fallait couper en blocs de 3o :
    A1 va recevoir 012
    A2 : 345
    A3 : 678
    STOP !
    Tu as rempli 3 bandes, tu vas calculer leur redondance !
    012 XOR 345 XOR 678
    Ce résultat tu l'écris sur Ap, et tu peux reprendre l'écriture...
    (attention ! Il faut accéder à A1, A2 et A3 pour obtenir leur contenu !)

    B1 : 9
    tu vas écrire 9 "tout seul"...
    CAD que tu vas juste remplir le 1er octet, et interroger les blocs B1, B2, B3, les XOR comme en haut, et mettre le résultat dans Bp

    Une fois cette opération terminée, quand tu vas faire un 'cat' de tes fichiers tu verras en gros :
    Fichier 1 (A1, B1, ...) :
    0129
    Fichier 2 (A2, B2, ...) :
    345
    Fichier 3 (A3, Bp, ...) :
    678xxx (3 caractères qui seront le résultat du XOR de B)
    Fichier 4 (Ap, B3, ...) :
    xxx (3 caractères qui seront le résultat du XOR de A)

    Il te faut donc une fonction pour écrire/lire les blcos de tailles 3o (et aussi le bloc de 2o).
    En gros il faut pouvoir choisir la lettre A-B-C-D-E-F, et le chiffre 1,2,3,p puis indiquer la taille que l'on écrit (inférieure ou égale à la taille du bloc en cours), et donner la donnée à recopier ou à extraire.

    EDIT : j'ai même pas regardé le schéma... je suis parti sur l'idée qu'il y aurait 1 disque supplémentaire en parité.... preuve que je ne regarde qu'à peine les docs....
    EDIT2 : maintenant c'est édité pour prise en compte de ce léger oubli !
    --
    Metalman !

    Attendez 5 mins après mes posts... les EDIT vont vite avec moi...
    Les flags de la vie : gcc -W -Wall -Werror -ansi -pedantic mes_sources.c
    gcc -Wall -Wextra -Werror -std=c99 -pedantic mes_sources.c
    (ANSI retire quelques fonctions comme strdup...)
    L'outil de la vie : valgrind --show-reachable=yes --leak-check=full ./mon_programme
    Et s'assurer que la logique est bonne "aussi" !

    Ma page Developpez.net

  7. #7
    Membre éprouvé
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Août 2011
    Messages
    756
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 31
    Localisation : France, Haute Garonne (Midi Pyrénées)

    Informations professionnelles :
    Activité : Ingénieur développement logiciels

    Informations forums :
    Inscription : Août 2011
    Messages : 756
    Par défaut
    Merci !!!

    Tu peux pas savoir à quel point ton exemple m'a aidé à y voir plus clair !

    Si je transpose mon énoncé avec ce que tu as dis, je suppose que lorsque tu parles de redondance, ça correspond au bloc de parité ?

    1) 4 disques de 20o chacun = 3 disques utilisables, et 1 de redondance
    CAD : 3 * 20 = 60o utilisables
    OK.


    2) Les bandes font 3o... c'est... pas génial... mais bon...
    20 / 3 = 6o
    Donc on va avoir 6 bandes de 3o sur chaque disque...
    3 * 6 = 18, 20 - 18 = 2o
    Et pour ne rien perdre : 1 bande supplémentaire de 2o (il vaut mieux perdre cet espace pour le moment... et ne pas s'en soucier)

    C'est là que j'ai décroché

    Pour moi une bande ce serait formé de A1 A2 A3 Ap où les A sont des blocs.
    Donc si on a un bloc qui fait 3o; la bande ne devrait elle pas faire 9 octet utilisable plus 3 octet pour le bloc de parité, redondance ?

    J'ai peut être compris de travers.

  8. #8
    Membre Expert
    Avatar de Metalman
    Homme Profil pro
    Enseignant-Chercheur
    Inscrit en
    Juin 2005
    Messages
    1 049
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 36
    Localisation : France, Hauts de Seine (Île de France)

    Informations professionnelles :
    Activité : Enseignant-Chercheur
    Secteur : Enseignement

    Informations forums :
    Inscription : Juin 2005
    Messages : 1 049
    Par défaut
    Voilà les images qui simulent ton exemple....

    Evidemment c'est en schématisant que tout vient :
    L'initialization met des '\0' sur toutes les bandes numérotées 1-3, et calcule le XOR de tous ces '\0' pour mettre le résultat dans les bandes p (normalement '\0' aussi si je ne me trompe pas trop trop...)


    EDIT : euh oui.... les bandes sont les A1-3-p... et chaque Ax est un bloc....
    Mais c'est qu'une erreur de vocabulaire de ma part....
    Si le schéma est "bien" ce que tu avais en tête, alors on s'est compris !
    Images attachées Images attachées   
    --
    Metalman !

    Attendez 5 mins après mes posts... les EDIT vont vite avec moi...
    Les flags de la vie : gcc -W -Wall -Werror -ansi -pedantic mes_sources.c
    gcc -Wall -Wextra -Werror -std=c99 -pedantic mes_sources.c
    (ANSI retire quelques fonctions comme strdup...)
    L'outil de la vie : valgrind --show-reachable=yes --leak-check=full ./mon_programme
    Et s'assurer que la logique est bonne "aussi" !

    Ma page Developpez.net

  9. #9
    Membre éprouvé
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Août 2011
    Messages
    756
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 31
    Localisation : France, Haute Garonne (Midi Pyrénées)

    Informations professionnelles :
    Activité : Ingénieur développement logiciels

    Informations forums :
    Inscription : Août 2011
    Messages : 756
    Par défaut
    Ouai je pense que c'est bien comme ça que je le visualisais.

    Si je me résume
    1 bloc de 3o
    1 bande de 9o donnée + 3o redondance
    4 disques 20o ==> 60o données + 20o redondance

    6 bloc sur un disque + 2o redondance par disque
    Et donc 6 bandes au total.



    Question par rapport au XOR; j'ai compris le principe; ça permettra de retrouver un bloc disparu; mais dans la pratique comment ça marche.

    Parce que, un xor c'est une opération mathématique; ou tout du moins une opération logique; donc pour implémenter ça en C avec les blocs qui eux contiennent des chaines de caractères ça va merder.
    Ou alors on applique le xor non pas sur le contenu mais sur les indices ?

    Enfin bref je vois ce que ça doit faire; mais je vois pas comment ça le fait


    Merci pour ton aide; je pense que je vais commencer à coder les premières fonctions sinon je vais parler dans le vide à partir de maintenant, tu m'as bien aidé à dégrossir le fonctionnement je t'en remercie énormément !

  10. #10
    Membre Expert
    Avatar de Metalman
    Homme Profil pro
    Enseignant-Chercheur
    Inscrit en
    Juin 2005
    Messages
    1 049
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 36
    Localisation : France, Hauts de Seine (Île de France)

    Informations professionnelles :
    Activité : Enseignant-Chercheur
    Secteur : Enseignement

    Informations forums :
    Inscription : Juin 2005
    Messages : 1 049
    Par défaut
    6 bloc sur un disque + 2o redondance par disque
    Plutôt 2o de "perdus" vu que l'on n'en fait rien...


    L'histoire du XOR c'est en effet une opération de logique/maths.
    A XOR B = C
    B XOR C = A
    C XOR A = B

    C'est toute la "beauté" de cette opération
    Et elle fonctionne aussi avec une taille indéfinie (cf wikipedia).

    Pour l'implémenter... ça va être une autre paire de manche, je l'admets.
    Le "XOR" tout seul existe en C... c'est ^

    Pour le cas "simple" de nos 3o, il faudra faire du XOR octet par octet...
    IRL, tu vas directement prendre des blocs de 32 ou 64 bits (4 ou 8 octets).

    En gros pour déduire Ap :
    1) Extraire A1, A2 et A3

    2) Stocker A1[0] ^ A2[0] ^ A3[0]
    3) Stocker A1[1] ^ A2[1] ^ A3[1]
    4) Stocker A1[2] ^ A2[2] ^ A3[2]

    5) Faire une chaîne de 3o avec les 3 valeurs stockées

    6) Ecrire en Ap la chaîne générée

    Ap[0] = A1[0] ^ A2[0] ^ A3[0]
    Ap[1] = A1[1] ^ A2[1] ^ A3[1]
    Ap[2] = A1[2] ^ A2[2] ^ A3[2]



    Quand un disque "disparait", il faut évidemment garder en mémoire lequel est "mort", et le remplacer par Ap lorsque l'on fait des appels à un des A1-3
    --
    Metalman !

    Attendez 5 mins après mes posts... les EDIT vont vite avec moi...
    Les flags de la vie : gcc -W -Wall -Werror -ansi -pedantic mes_sources.c
    gcc -Wall -Wextra -Werror -std=c99 -pedantic mes_sources.c
    (ANSI retire quelques fonctions comme strdup...)
    L'outil de la vie : valgrind --show-reachable=yes --leak-check=full ./mon_programme
    Et s'assurer que la logique est bonne "aussi" !

    Ma page Developpez.net

  11. #11
    Membre éprouvé
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Août 2011
    Messages
    756
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 31
    Localisation : France, Haute Garonne (Midi Pyrénées)

    Informations professionnelles :
    Activité : Ingénieur développement logiciels

    Informations forums :
    Inscription : Août 2011
    Messages : 756
    Par défaut
    Ok; donc j'ai commencé à coder en fonction de ce que j'ai compris et de ce que l'on me demande.

    On considère que notre système RAID 5 est représenté par la variable globale virtual_disk_t g_disk ;.
    Avant de pouvoir l’utiliser, il est nécessaire de l’initialiser à partir du nom du répertoire contenant les disques virtuels formatés. Ecrire la fonction init disk raid5 qui, à partir du nom du répertoire, initialise cette variable globale. Dans un premier temps, on n’initialisera pas la table d’inodes.
    Lorsque notre système sera ” éteint”, il sera nécessaire de s’assurer de l’absence de risque de perte de données. Pour cela, écrire une fonction qui ” éteint” notre système RAID 5.

    Toujours en prenant appuie sur le header du premier message

    J'ai déclaré deux variables en global dans mon header.

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    virtual_disk_t g_disk;
    DIR* rep = NULL
    Puis j'ai fait la fonction init pour allumer le système et la fonction pour l'éteindre.

    Je suis pas sûr à 100% d'avoir bien transcris l'énoncé pour l'initialisation en tout cas.

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    void init_disk_raid5(char* adresse)
    {
    	g_disk.ndisk=NUMBER_OF_DISKS;
    	g_disk.raidmode=5;
        rep = opendir(adresse);
    		g_disk.storage[0]=fopen("d0","r");	
    	g_disk.storage[1]=fopen("d1","r");
    g_disk.storage[2]=fopen("d2","r");
    g_disk.storage[3]=fopen("d3","r");
     
    }
     
    void close_disk_raid5(char* adresse)
    {
    	int k;
    	for(k=0;k<g_disk.ndisk;k++)
        {
    		fclose(g_disk.storage[k]);	
    	}
    	closedir(rep);
    }
    Il est possible que le code ne compile pas; j'ai surtout voulu montrer la démarche pour voir si j'avais compris dans le bon sens ou pas.

  12. #12
    Membre prolifique
    Avatar de Sve@r
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Février 2006
    Messages
    12 832
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Oise (Picardie)

    Informations professionnelles :
    Activité : Ingénieur développement logiciels
    Secteur : Aéronautique - Marine - Espace - Armement

    Informations forums :
    Inscription : Février 2006
    Messages : 12 832
    Billets dans le blog
    1
    Par défaut
    Citation Envoyé par Amnael Voir le message
    J'ai déclaré deux variables en global dans mon header.

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    virtual_disk_t g_disk;
    DIR* rep = NULL
    Il est possible que le code ne compile pas; j'ai surtout voulu montrer la démarche pour voir si j'avais compris dans le bon sens ou pas.
    Salut
    Es-tu certain d'avoir besoin de variables "globales" ??? Les globales c'est utile vu que ça a été créé mais c'est aussi super dangereux et super limitatif (par exemple tu ne pourras pas utiliser plus d'un seul raid par programme)...
    Mon Tutoriel sur la programmation «Python»
    Mon Tutoriel sur la programmation «Shell»
    Sinon il y en a pleins d'autres. N'oubliez pas non plus les différentes faq disponibles sur ce site
    Et on poste ses codes entre balises [code] et [/code]

  13. #13
    Membre Expert
    Avatar de Metalman
    Homme Profil pro
    Enseignant-Chercheur
    Inscrit en
    Juin 2005
    Messages
    1 049
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 36
    Localisation : France, Hauts de Seine (Île de France)

    Informations professionnelles :
    Activité : Enseignant-Chercheur
    Secteur : Enseignement

    Informations forums :
    Inscription : Juin 2005
    Messages : 1 049
    Par défaut
    Ca a l'air d'être un énoncé... on va pas contredire "à chaque fois" qu'il y a une globale surtout quand c'est un exercice.
    Enfin au moins il le saura que c'est "à éviter" tu vas me dire
    EDIT : par contre Sve@r a raison à propos du répertoire... pas besoin de le mettre en global !

    Bref, en relisant 2-3 fois ta première déclaration et ta globale je pense avoir compris comment c'est organisé pour ton projet.

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    #ifndef __R5_DEFINES__
    #define __R5_DEFINES__
     
    #define NUMBER_OF_DISKS 4
    #define BLOCK_SIZE 4
    #define FILENAME_MAX_SIZE 32
    #define MAX_FILES 100
    #define MAX_FILE_SIZE (50*1024)
     
     
    typedef unsigned int uint;
    typedef unsigned char uchar;
     
    /* Type of a block of data */
    typedef struct block_s{
        uchar data[BLOCK_SIZE];
    } block_t;
     
    /* Type of the pseudo-inode structure */
    typedef struct inode_s{
      char filename[FILENAME_MAX_SIZE];
      uint size;
      uint nblock; // nblock = (size+BLOCK_SIZE-1)/BLOCK_SIZE
      uint block_id;
    } inode_t;
     
    /* Type of the inode table */
    typedef inode_t inode_table_t[MAX_FILES];
     
    /* Type of the virtual disk system */
    typedef struct virtual_disk_s {
        inode_table_t inodes;
        int ndisk;
        int raidmode;
        FILE *storage[NUMBER_OF_DISKS];
    } virtual_disk_t;
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    virtual_disk_t g_disk;
    DIR* rep = NULL
    virtual_disk : c'est l'espace disque qui sera "utilisable" par l'utilisateur du RAID
    virtual_disk_t : type qui contient une grappe de disques (des FILE* dans notre cas), le type de raid, le nb de disques, et une table d'inodes [au début je croyais qu'il fallait écrire la table d'inodes dans le RAID !... en fait non elle est bien à part)
    inode_table_t : type qui est en fait un tableau d'inodes
    inode_t : type inode qui contient un nom de fichier, une taille de fichier, le nb de blocs alloués, et l'ID du 1er bloc
    block_t : un bloc... c'est simplement "un" caractère non signé [non, c'est bel et bien plusieurs caractères]

    Comme les blocs sont en fait des caractères, pour pouvoir "contenir" des '\0' (c'est aussi une donnée en soi...) dans des fichiers, on indiquer le 1er bloc alloué, et le nb de blocs associés au fichier.

    Je suppose que pour l'exercice, les fichiers ne peuvent pas être de taille variable. (les inodes ne ressemblent pas aux inodes à la sauce linux où il y a des sauts entre plusieurs inodes)
    Tout ce que l'on a essayé de faire depuis le début est correct donc, il faudra "juste" passer par l'interface fournie pour écrire caractère par caractère !


    A propos des fonctions d'ouverture et de fermeture :
    - la fermeture est correcte... à ceci près que tu peux faire le closedir dans l'ouverture du RAID
    - l'ouverture est très très.... elle marche clairement pas... mais l'idée est là (et tu peux faire un closedir après avoir ouvert tes 4 fichiers/disques)

    L'ouverture va fonctionner ainsi :
    1) on ouvre le dossier
    2) on cherche les 4 fichiers en itérant dans le dossier
    3) on ouvre un à un chaque fichier (si UN seul fichier manque, le RAID sera en mode dégradé, s'il en manque + d'un, alors le RAID est cassé, et on annule l'ouverture et on écrit un gros message d'erreur, par exemple)
    4) une fois les 3 ou 4 fichiers chargés, on ferme le répertoire

    Pour le chargement de la table d'inodes... je... ne comprends pas encore comment ça va se faire en fait...
    Mais si tu as un énoncé complet qui te le dit, tant mieux !
    --
    Metalman !

    Attendez 5 mins après mes posts... les EDIT vont vite avec moi...
    Les flags de la vie : gcc -W -Wall -Werror -ansi -pedantic mes_sources.c
    gcc -Wall -Wextra -Werror -std=c99 -pedantic mes_sources.c
    (ANSI retire quelques fonctions comme strdup...)
    L'outil de la vie : valgrind --show-reachable=yes --leak-check=full ./mon_programme
    Et s'assurer que la logique est bonne "aussi" !

    Ma page Developpez.net

  14. #14
    Membre prolifique
    Avatar de Sve@r
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Février 2006
    Messages
    12 832
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Oise (Picardie)

    Informations professionnelles :
    Activité : Ingénieur développement logiciels
    Secteur : Aéronautique - Marine - Espace - Armement

    Informations forums :
    Inscription : Février 2006
    Messages : 12 832
    Billets dans le blog
    1
    Par défaut
    Citation Envoyé par Metalman Voir le message
    Ca a l'air d'être un énoncé... on va pas contredire "à chaque fois" qu'il y a une globale surtout quand c'est un exercice.
    Héhé, tout exercice est quand-même fait pour aussi donner les bonnes habitudes
    Citation Envoyé par Metalman Voir le message
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    /* Type of a block of data */
    typedef struct block_s{
        uchar data[BLOCK_SIZE];
    } block_t;
    block_t : un bloc... c'est simplement "un" caractère non signé
    Euh c'est plutôt un tableau de "n" caractères
    Citation Envoyé par Metalman Voir le message
    Mais si tu as un énoncé complet qui te le dit, tant mieux !
    Moi j'aime beaucoup ce TP et je dis chapeau au prof qui l'a pondu et qui est capable de le corriger. Et j'aimerais bien avoir l'énoncé pour m'amuser à le faire de mon coté...
    Mon Tutoriel sur la programmation «Python»
    Mon Tutoriel sur la programmation «Shell»
    Sinon il y en a pleins d'autres. N'oubliez pas non plus les différentes faq disponibles sur ce site
    Et on poste ses codes entre balises [code] et [/code]

  15. #15
    Membre Expert
    Avatar de Metalman
    Homme Profil pro
    Enseignant-Chercheur
    Inscrit en
    Juin 2005
    Messages
    1 049
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 36
    Localisation : France, Hauts de Seine (Île de France)

    Informations professionnelles :
    Activité : Enseignant-Chercheur
    Secteur : Enseignement

    Informations forums :
    Inscription : Juin 2005
    Messages : 1 049
    Par défaut
    Oups... oui en effet le bloc est composé de N caractères.... my bad...

    Moi aussi ça me donne envie de le faire du coup... ^^'
    Amnael... tu nous file l'énoncé complet ?
    --
    Metalman !

    Attendez 5 mins après mes posts... les EDIT vont vite avec moi...
    Les flags de la vie : gcc -W -Wall -Werror -ansi -pedantic mes_sources.c
    gcc -Wall -Wextra -Werror -std=c99 -pedantic mes_sources.c
    (ANSI retire quelques fonctions comme strdup...)
    L'outil de la vie : valgrind --show-reachable=yes --leak-check=full ./mon_programme
    Et s'assurer que la logique est bonne "aussi" !

    Ma page Developpez.net

  16. #16
    Membre éprouvé
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Août 2011
    Messages
    756
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 31
    Localisation : France, Haute Garonne (Midi Pyrénées)

    Informations professionnelles :
    Activité : Ingénieur développement logiciels

    Informations forums :
    Inscription : Août 2011
    Messages : 756
    Par défaut
    De retour à la civilisation j'ai pu mettre le pdf en pièce jointe; Have fun

    Et désolé pour le temps sans réponse, je n'avais plus d'internet jusqu'à ce soir !
    Images attachées Images attachées

  17. #17
    Membre éprouvé
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Août 2011
    Messages
    756
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 31
    Localisation : France, Haute Garonne (Midi Pyrénées)

    Informations professionnelles :
    Activité : Ingénieur développement logiciels

    Informations forums :
    Inscription : Août 2011
    Messages : 756
    Par défaut
    Je me replonge dès aujourd'hui dans ce projet; une semaine top chrono

    Pour le répertoire en global; c'était très maladroit je vous l'accorde je ne m'en suis rendu compte qu'après coup; le répertoire étant dépendant de l'adresse il n'y a aucune raison de le déclarer en global, je suis OK sur ce point.

    L'ouverture va fonctionner ainsi :
    1) on ouvre le dossier
    2) on cherche les 4 fichiers en itérant dans le dossier
    3) on ouvre un à un chaque fichier (si UN seul fichier manque, le RAID sera en mode dégradé, s'il en manque + d'un, alors le RAID est cassé, et on annule l'ouverture et on écrit un gros message d'erreur, par exemple)
    4) une fois les 3 ou 4 fichiers chargés, on ferme le répertoire

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    void init_disk_raid5(char* adresse)
    {
    	DIR* rep = NULL;
    	g_disk.ndisk=NUMBER_OF_DISKS;
    	g_disk.raidmode=5;
        rep = opendir(adresse); /*1*/
        /*3*/
    		g_disk.storage[0]=fopen("d0","r");
                    g_disk.storage[1]=fopen("d1","r");
                    g_disk.storage[2]=fopen("d2","r");
                    g_disk.storage[3]=fopen("d3","r");	
    	/*3*/
    closedir(rep);/*4*/
    }
    1 - OK; mais comment gérer une erreur du style l'adresse entré n'est pas celle d'un dossier mais même à un fichier par exemple.
    (Ici je pense que je peux définir l'adresse avec une constante vu que le raid sera automatiquement dans un même dossier; mais par curiosité j'aimerais savoir comment on gérerait un test de ce genre.

    2 - J'avoue ne pas trop savoir comment parcourir le dossier et arriver à lister son contenu. Après plusieurs recherches j'ai pu dénicher une bibliothèque dirent.h qui permettrait ce genre de choses, mais je suis pas sur de tout avoir compris sur ce point là. N'y as t'il pas un moyen de faire sans bibliothèques supplémentaires ?

    3 - OK; c'est ce que j'ai fait en supposant qu'ils sont effectivement présent il faut donc rajouter la condition 2 là dessus.


    4 - Ok; je n'ai qu'à faire passer ma fermeture dans cette fonction là; mais en réalité je pensais que fermer le dossier pourrait avoir une incidence sur les fichiers déjà ouverts.

    EDIT

    Après modification voilà ce que ça donne
    Je fais bien le test je pense; mais ça n'est pas non plus de la gestion d'erreur; l'affichage ne mettra pas un terme au programme; peut être y a t'il un code similaire au exit en sh pour faire en sorte que lorsque le raid est cassé l'on quitte automatiquement le programme ?

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    void init_disk_raid5(char* adresse)
    {
    	DIR* rep = NULL;
    	g_disk.ndisk=NUMBER_OF_DISKS;
    	g_disk.raidmode=5;
    	int nbFich=4;
        rep = opendir(adresse);
        int fich=nbFich;
    	g_disk.storage[0]=fopen("d0","r");
    	g_disk.storage[1]=fopen("d1","r");
    	g_disk.storage[2]=fopen("d2","r");
    	g_disk.storage[3]=fopen("d3","r");	
    	closedir(rep);
    	int k;
    	for (k=0;k<g_disk.ndisk;k++)
    	{
    		if (g_disk.storage[k]==NULL)
    		{
    			fich=(fich-1);
    		}
    	}
    	if (fich < nbFich-2)
    	{
    		printf("Deux fichiers ou plus manquant\n RAID5 cassé \n");
    	}
     
    }

  18. #18
    Membre prolifique
    Avatar de Sve@r
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Février 2006
    Messages
    12 832
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Oise (Picardie)

    Informations professionnelles :
    Activité : Ingénieur développement logiciels
    Secteur : Aéronautique - Marine - Espace - Armement

    Informations forums :
    Inscription : Février 2006
    Messages : 12 832
    Billets dans le blog
    1
    Par défaut
    De retour moi-aussi. J'ai lu attentivement le sujet. je trouve le barème super hard (si un programme ne compile pas => 0 !!!).

    Bon, ceci dit, je regarde ton code. Exemple
    Code c : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    g_disk.storage[0]=fopen("d0","r");
    g_disk.storage[1]=fopen("d1","r");
    g_disk.storage[2]=fopen("d2","r");
    g_disk.storage[3]=fopen("d3","r");
    Et ainsi de partout ce qui signifie (avec ces instructions identiques x4) que tu pars billes en têtes sur un système de 4 disques. Mais as-tu lu cette partie
    Pour effectuer vos tests, nous vous conseillons les valeur suivantes de ces constantes.
    #define NUMBER OF DISKS 4
    #define BLOCK SIZE 4
    #define FILENAME MAX SIZE 32
    #define MAX FILES 100
    #define MAX FILE SIZE (50∗1024)
    Veuillez vous assurer toutefois que si on change leur valeurs, votre système doit rester opérationnel.
    Ca signifie que ton système devra fonctionner à l'identique pour 3 ou 300 disques !!!
    Donc déjà il faut immédiatement remplacer toutes tes opérations à 4 disques par des opérations à N disques (avec itération de tableaux !!!)
    Je dis "immédiatement" parce que plus tôt on détecte une faille de ce genre de la rectifier plus facile il est (tiens, je parle comme Yoda ).

    PS: j'aime bien cette partie
    Attention, un outil de détection de la copie sera utilisée sur les archives déposées. Toute copie avérée entrainera la note de 0 au projet et une convocation par le directeur des études et le responsable de l’unité d’enseignement.
    Moi, je dis qu'un prof d'info qui n'est pas capable de mettre des droits intelligents sur son dossier de rendu de TP pour que l'élève Dupond ne puisse pas récupèrer le travail de l'élève Durand mérite de se faire hacker et mérite de se faire convoquer tout seul par le directeur des études pendant que le hackeur prend sa place...

    L’exemple fourni dans cmd format peut être analysé pour servir de base à l'écriture des autres programmes demandés.
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    // si on appelle
    #./ cmd format hello 500 2
    ... surtout quand en plus il bosse en permanence sous root.
    Mon Tutoriel sur la programmation «Python»
    Mon Tutoriel sur la programmation «Shell»
    Sinon il y en a pleins d'autres. N'oubliez pas non plus les différentes faq disponibles sur ce site
    Et on poste ses codes entre balises [code] et [/code]

  19. #19
    Membre Expert
    Avatar de Metalman
    Homme Profil pro
    Enseignant-Chercheur
    Inscrit en
    Juin 2005
    Messages
    1 049
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 36
    Localisation : France, Hauts de Seine (Île de France)

    Informations professionnelles :
    Activité : Enseignant-Chercheur
    Secteur : Enseignement

    Informations forums :
    Inscription : Juin 2005
    Messages : 1 049
    Par défaut
    Pour la copie => tu peux rendre la même tarball que ton copain... ça n'est pas du hack, et nécessite encore moins de capacités à réfléchir

    Le 0 en cas de non compilation, c'est "normal"... enfin à mon goût... on fait de l'informatique, c'est le minimum de rendre un truc qui compile.
    Le barème est même très tolérant comparé à d'autres écoles...
    Mais bref, ça n'est pas le but de la discussion....


    Pour la navigation dans les dossiers, remets ton code au propre, déjà !
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    void init_disk_raid5(char* adresse)
    {
    	DIR* rep = NULL;
    	int nbFich=4;
    	int fich=nbFich;
    	int k;
     
    	g_disk.ndisk=NUMBER_OF_DISKS;
    	g_disk.raidmode=5;
     
    	rep = opendir(adresse);
     
    	g_disk.storage[0]=fopen("d0","r");
    	g_disk.storage[1]=fopen("d1","r");
    	g_disk.storage[2]=fopen("d2","r");
    	g_disk.storage[3]=fopen("d3","r");
     
    	closedir(rep);
     
    	for (k=0;k<g_disk.ndisk;k++)
    	{
    		if (g_disk.storage[k]==NULL)
    		{
    			fich=(fich-1);
    		}
    	}
    	if (fich < nbFich-2)
    	{
    		printf("Deux fichiers ou plus manquant\n RAID5 cassé \n");
    	}
     
    }
    Tu ne construis pas le chemin absolu depuis ton dossier, c'est dommage (mais chiant à faire)....
    En effet, tu ouvres un répertoire, te balades dedans et tu ouvres des fichiers en dur.
    Bref....
    Entre le openddir et le closedir, tu dois faire des readdir ! [man section 3.... et non section 2 comme je m'étais dans un autre topic...]
    Chaque readdir te renverra une structure correspondant à UN fichier...
    Il faut donc itérer autant de fois que nécessaire (jusqu'à ce qu'il te renvoit NULL).

    La structure dirent ressemble à peu près à ça :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    struct dirent {
        ino_t          d_ino;       /* numéro d'inœud */
        off_t          d_off;       /* décalage jusqu'à la dirent suivante */
        unsigned short d_reclen;    /* longueur de cet enregistrement */
        unsigned char  d_type;      /* type du fichier */
        char           d_name[256]; /* nom du fichier */
    };
    d_type va te donner le type de fichier que tu as actuellement... la valeur DT_REG dit que c'est un fichier !
    Et d_name contient le chemin absolu du fichier... que tu peux donner à fopen !

    Seule question (peut être à poser au prof/j'ai mal lu le sujet) : où sont les noms des fichiers qui gèrent les disques ? Qui les donne ?
    --
    Metalman !

    Attendez 5 mins après mes posts... les EDIT vont vite avec moi...
    Les flags de la vie : gcc -W -Wall -Werror -ansi -pedantic mes_sources.c
    gcc -Wall -Wextra -Werror -std=c99 -pedantic mes_sources.c
    (ANSI retire quelques fonctions comme strdup...)
    L'outil de la vie : valgrind --show-reachable=yes --leak-check=full ./mon_programme
    Et s'assurer que la logique est bonne "aussi" !

    Ma page Developpez.net

  20. #20
    Membre éprouvé
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Août 2011
    Messages
    756
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 31
    Localisation : France, Haute Garonne (Midi Pyrénées)

    Informations professionnelles :
    Activité : Ingénieur développement logiciels

    Informations forums :
    Inscription : Août 2011
    Messages : 756
    Par défaut
    Le nom des disques est généré par un script

    Le nom ce sera toujours d suivi du numéro du disque=fichier.

    Pour ce qui est du readdir là encore je découvre è_é

    En fait on a pas eu un seul cours dans lequel on nous as appris la syntaxe et donc on doit tout chercher nous mêmes...je comprends le but mais je trouve quand meme ça un peu dommage

    Pour faire ce que j'ai fait je me suis renseigné sur le sdz.

    Mais il n'y a pas de mention sur readdir.

    En ce qui concerne le fait d'adapter au nombre de disques; OK mais dans la pratique ça veut dire que je dois concaténer un numéro au dte

    En fait un truc qui ressemblerait à ça même si le code que je présente là n'est pas correct

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    for(k=0;k<g_disk.ndisk;k++)
        {
    g_disk.storage[k]=fopen("dk","r");
    }
    Je vais tout de suite chercher s'il y a quelque chose pour faire cette espèce de concaténation; mais je me rappelle avoir voulu faire cela au début sans succès.



    Voilà à quoi j'ai pensé comme solution.

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
     
    for(k=0;k<NUMBER_OF_DISK;k++)
        {
    fichier[FILENAME_MAX_SIZE]="d";
    strcat(fichier,"%d",k);
    g_disk.storage[k]=fopen("fichier","r");
    }
    Mais j'ai pas mal de doutes; est ce que je peux concaténer la valeur de k avec strcat ou bien ça va me prendre la chaine %d,k
    Ensuite en mettant fichier dans le fopen comprendra il la variable fichier ou bien la chaine fichier.

    EDIT 3

    J'ai trouvé la fonction pour faire ça c'est sprintf.

    par contre je suis pas sur de comment ça doit marcher; à priori les fichiers ne peuvent porter comme nom que d0...dn mais pourtant la taille maximale va jusqu'à 32 ce qui serait absurde si on devait restreindre les noms.

Discussions similaires

  1. [Débutant] Simulation de l'instabilité d'un système d'équations couplées
    Par funky2401 dans le forum MATLAB
    Réponses: 9
    Dernier message: 25/06/2008, 14h19
  2. simulation d'un système solaire
    Par cecile.7.07 dans le forum Algorithmes et structures de données
    Réponses: 8
    Dernier message: 30/03/2007, 11h44
  3. simulation du déplacement d'un agent mobile dans un système distribué en java
    Par f25diablovos dans le forum Interfaces Graphiques en Java
    Réponses: 2
    Dernier message: 04/09/2006, 16h28
  4. [Système] Simuler un formulaire avec fsockopen()
    Par cyriltra dans le forum Langage
    Réponses: 6
    Dernier message: 25/07/2006, 21h35
  5. Simuler l'appui sur une touche, au niveau système
    Par debutant java dans le forum AWT/Swing
    Réponses: 5
    Dernier message: 13/08/2004, 12h51

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo