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 :

Programmer ls|wc|wc en C


Sujet :

C

Vue hybride

nocheb Programmer ls|wc|wc en C 12/03/2012, 05h19
Neckara N'oublie pas d'indenter ton... 12/03/2012, 07h11
Trademark C'est un exo typique pour... 12/03/2012, 08h30
gangsoleil Independamment de ton code... 12/03/2012, 15h18
Bktero Une bonne partie de la... 12/03/2012, 23h19
gangsoleil C'est bien pour ca que je... 13/03/2012, 09h39
Bktero Ah en plus il ajuste le... 13/03/2012, 10h05
nocheb Voici qui marche ls|wc|wc 13/03/2012, 16h22
Message précédent Message précédent   Message suivant Message suivant
  1. #1
    Futur Membre du Club
    Inscrit en
    Février 2009
    Messages
    3
    Détails du profil
    Informations forums :
    Inscription : Février 2009
    Messages : 3
    Par défaut Programmer ls|wc|wc en C
    Bonjour à tous, je débute en Programmation système en C sous Linux et voici le code en C de l'ensemble de la commande ls|wc|wc, il compile bien mais le programme ne s'execute pas, je ne sais pas trop pourquoi, que se passe-t-il ? :

    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
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    #include <stdio.h>
    #include <memory.h>
    #include <unistd.h>
     
    int main (int argc, char ** argv)
    {
    	/* creation du tube */
    	int tube[2];
    	if (pipe(tube) == -1)
    	{
    		printf ("la creation du tube a echoué\n");
    		return 0;
    	}
    	int pid;
    	if ((pid=fork())<0)
    	{ 
    		printf("primitive fork à echoué");
    		return 2;
    	}
     
    	if((pid = fork())==0)
    	{
    		{
    		close(tube[0]);
    		dup2(tube[0], 1);
    		close(tube[1]);
    		execlp("wc", "wc", (char *) 0);
    		printf("la commande wc a echouée");
    		return 3;
    		}
     
    		{
    			close(tube[0]);
    			dup2(tube[0], 1);
    			close(tube[1]);
    			execlp("ls","ls",(char *)0);
    			printf("la commande ls a echouée");
    			return 4;
    		}
    	}
     
    		else/*(pid > 0)*/
    		{
    			{
    			close(tube[1]);
    			dup2(tube[1], 0);
    			close(tube[0]);
    			execlp("wc", "wc", (char *) 0);
    		        printf("la commande wc a echouée");
    				return 5;
    			}
     
    			{
    				close(tube[1]);
    				dup2(tube[1], 0);
    				close(tube[0]);
    				execlp("wc","wc",(char *) 0);
    				return 6;
    			}
    		}
    		return 0;
    	}

  2. #2
    Inactif  


    Homme Profil pro
    Doctorant sécurité informatique — Diplômé master Droit/Économie/Gestion
    Inscrit en
    Décembre 2011
    Messages
    9 026
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 32
    Localisation : France, Loire (Rhône Alpes)

    Informations professionnelles :
    Activité : Doctorant sécurité informatique — Diplômé master Droit/Économie/Gestion
    Secteur : Enseignement

    Informations forums :
    Inscription : Décembre 2011
    Messages : 9 026
    Par défaut
    N'oublie pas d'indenter ton code et de mettre les balises CODE

    Ce que tu fait n'as pas tellement d'utilité en C.
    Là, tu dis : ouvre-moi un terminal et exécute-moi ce code en shell puis reviens au programme en C.
    EDIT : le matin ça ne me réussit pas^^
    Donc tu lui dis : remplace mon programme en C par l'exécution de "ls etc..." dans un shell.

    Autant faire un script-shell.

    Dans man dirent tu devrais trouver des informations pour pouvoir parcourir les dossier ie coder un 'ls' en C.
    Avec fopen, fclose et fscanf tu devrais pouvoir compter le nombre de mot d'un fichier.
    Pour savoir le nombre de ligne, utilise un fgets, pour compter le nombre de caractère, un fseek et un ftell devraient être suffisant.

    Tu seras 1 000 fois plus rapide dans l'exécution.

    On sait ce qu'il se passe, mais on ne sait pas ce que toi tu voulais que cela fasse, met plutôt NULL. (stddef.h inclus dans stdlib.h)
    On ne sait pas ce que tu veux faire.
    Pour plus de lisibilité utilise
    STDIN_FILENO
    STDOUT_FILENO
    STDERR_FILENO

    EDIT : tu utilises un seul tube au lieu d'en utiliser deux.
    A moins d'utiliser des verrous, tu ne peux pas utiliser un seul tube avec 3 processus.

  3. #3
    Membre Expert Avatar de Trademark
    Profil pro
    Inscrit en
    Février 2009
    Messages
    762
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Février 2009
    Messages : 762
    Par défaut
    C'est un exo typique pour comprendre comment ça se passe derrière un shell donc pas la peine de vouloir faire autrement neckara ^^.

    Le premier problème est là :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    if ((pid=fork())<0)
    {
    printf("primitive fork à echoué");
    return 2;
    }
     
    if((pid = fork())==0)
    {
    {
    close(tube[0]);
    Tu fais un premier fork, si il échoue tu return (d'ailleurs pour ce genre d'erreur le mieux c'est de faire :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    perror("fork"); exit(EXIT_FAILURE);
    Enfin je trouve ça plus propre que de renvoyer des codes inconnu à la volée.
    Je m'égare, ce n'est pas le problème. En fait, si ton fork réussi il va y avoir deux processus qui vont aller refaire un deuxième fork dans ton if. Donc en tout tu auras 4 processus à ce moment...

    Pourquoi utilises-tu "{{" après ton if ? C'est inutile. En plus après lecture, je ne sais pas ce que tu crois ce que tu fais, mais dit toi que ça ne le fait pas

    Ce qui me dérange ensuite c'est ça :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
     
    close(tube[0]);
    dup2(tube[0], 1);
    close(tube[1]);
    Tu fermes le mauvais côté... Tu ne peux pas faire un dup2 sur un truc que tu viens de fermer... D'ailleurs vérifie le retour du dup2, il te mettra probablement une erreur.

    Sinon il te faudra 2 "paires" de tube (donc deux tableaux t[2]) pour représenter les deux pipes.

    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
    pid_t pid = fork()
    if(pid == 0)
    {
      pid = fork();
      if(pid == 0)
      {
    // processus petit fils(ls)
      }
      else
      {
    // processus fils (1er wc)
      }
    }
    else
    {
    // processus père (ls)
    }
    }
    C'est la hiérarchie a adopté, maintenant débrouille toi pour les tubes
    En exo supplémentaire, tu pourrais essayer de coder ça via une boucle pour pouvoir faire autant de pipe que tu en as envie.

  4. #4
    Modérateur
    Avatar de gangsoleil
    Homme Profil pro
    Manager / Cyber Sécurité
    Inscrit en
    Mai 2004
    Messages
    10 150
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Haute Savoie (Rhône Alpes)

    Informations professionnelles :
    Activité : Manager / Cyber Sécurité

    Informations forums :
    Inscription : Mai 2004
    Messages : 10 150
    Par défaut
    Citation Envoyé par nocheb Voir le message
    voici le code en C de l'ensemble de la commande ls|wc|wc
    Independamment de ton code qui est cense simuler cet enchainement, as-tu execute ces commandes ? Sais-tu ce qu'elles font ? Et es-tu bien certain que c'est cet enchainement qui t'est demande ?
    "La route est longue, mais le chemin est libre" -- https://framasoft.org/
    Les règles du forum

  5. #5
    Modérateur

    Avatar de Bktero
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Juin 2009
    Messages
    4 493
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 37
    Localisation : France, Loire Atlantique (Pays de la Loire)

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

    Informations forums :
    Inscription : Juin 2009
    Messages : 4 493
    Billets dans le blog
    1
    Par défaut
    Une bonne partie de la journée, je me suis posé la question "mais que renvoie la commande ls | wc | wc ?!". Je n'avais pas de Linux sous la main et la remarque de gangsoleil m'a encore plus donné envie de rentrer chez moi pour tester.

    Après test, je ne comprend pas du tout l'intérêt d'une telle commande...

  6. #6
    Modérateur
    Avatar de gangsoleil
    Homme Profil pro
    Manager / Cyber Sécurité
    Inscrit en
    Mai 2004
    Messages
    10 150
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Haute Savoie (Rhône Alpes)

    Informations professionnelles :
    Activité : Manager / Cyber Sécurité

    Informations forums :
    Inscription : Mai 2004
    Messages : 10 150
    Par défaut
    Citation Envoyé par Bktero Voir le message
    "mais que renvoie la commande ls | wc | wc ?!".

    Après test, je ne comprend pas du tout l'intérêt d'une telle commande...
    C'est bien pour ca que je pose la question :
    ls | wc | wc va toujours afficher la meme chose en fait : le nombre de lignes/mots/caracteres que produit la sortie standard de wc, c'est a dire 1 ligne, 3 mots, et pour le nombre de caracteres, il est theoriquement possible que cela change, mais vu que wc padd avec des espaces, il n'y a en fait que peu de chances (theorie : si la sortie de ls a besoin de plus de 7 chiffres pour compter le nombre de bytes).

    Refaire coder des commandes, je comprends. Utiliser des pipes, je comprends. Mais faire une fonction qui affiche toujours la meme chose, j'ai un peu de mal a voir l'interet.
    "La route est longue, mais le chemin est libre" -- https://framasoft.org/
    Les règles du forum

  7. #7
    Modérateur

    Avatar de Bktero
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Juin 2009
    Messages
    4 493
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 37
    Localisation : France, Loire Atlantique (Pays de la Loire)

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

    Informations forums :
    Inscription : Juin 2009
    Messages : 4 493
    Billets dans le blog
    1
    Par défaut
    Ah en plus il ajuste le nombre d'espaces ! Je m'étais dit qu'à la limite le 25 pourrait devenir autre chose mais finalement peut-être pas ^^

  8. #8
    Futur Membre du Club
    Inscrit en
    Février 2009
    Messages
    3
    Détails du profil
    Informations forums :
    Inscription : Février 2009
    Messages : 3
    Par défaut Voici qui marche ls|wc|wc
    Merci à tous :


    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
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    #define _XOPEN_SOURCE 600
    #include <sys/types.h>
     
    #include <stdlib.h>
    #include <unistd.h>
     
     
    static pid_t
    pipe_fork(void)
    {
    	int pfd[2];
    	pid_t pid;
     
    	if (pipe(pfd) < 0)
    		return -1;
     
    	if ((pid = fork()) < 0)
    		return -1;
     
    	if (pid == 0) {
    		close(pfd[0]);
    		dup2(pfd[1], STDOUT_FILENO);
    	} else {
    		close(pfd[1]);
    		dup2(pfd[0], STDIN_FILENO);
    	}
     
    	return pid;
    }
     
     
    int
    main(void)
    {
    	pid_t pid;
     
    	if ((pid = pipe_fork()) < 0)
    		return EXIT_FAILURE;
     
    	if (pid == 0)
    		switch (pipe_fork()) {
    		case -1:
    			return EXIT_FAILURE;
     
    		case 0:
    			execlp("ls", "ls", (char *)0);
    			break;
     
    		default:
    			execlp("wc", "wc", (char *)0);
    			break;
    		}
    	else
    		execlp("wc", "wc", (char *)0);
     
    	return EXIT_SUCCESS;
    }

+ Répondre à la discussion
Cette discussion est résolue.

Discussions similaires

  1. Programme de boot qui passe la main à Windows
    Par Bob dans le forum Assembleur
    Réponses: 7
    Dernier message: 25/11/2002, 03h08
  2. [Kylix] Probleme d'execution de programmes...
    Par yopziggy dans le forum EDI
    Réponses: 19
    Dernier message: 03/05/2002, 14h50
  3. communication entre programmes
    Par jérôme dans le forum C
    Réponses: 12
    Dernier message: 16/04/2002, 08h05
  4. Comment débuter en programmation ?
    Par Marc Lussac dans le forum Débuter
    Réponses: 0
    Dernier message: 08/04/2002, 11h29
  5. [Kylix] icone associée à un programme
    Par Anonymous dans le forum EDI
    Réponses: 1
    Dernier message: 22/03/2002, 09h43

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