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

Linux Discussion :

lancer une commande et récupérer son pid en C


Sujet :

Linux

  1. #1
    Membre à l'essai
    Profil pro
    Inscrit en
    Septembre 2006
    Messages
    39
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Septembre 2006
    Messages : 39
    Points : 13
    Points
    13
    Par défaut lancer une commande et récupérer son pid en C
    bonjour.
    je programme en C/C++ et je cherche une fonction qui lance un processus et qui récupère son pid.

    du genre
    int system(char* commande)
    ou l'integer renvoyé serait le pid de la commande
    j'ai essayer pas mal de trucs du genre récupérer ce qui s'affiche a l'ecran lorsque l'on fait un :
    commande >> /dev/null &
    ca nous affiche le pid mais je n'arrives pas a le metre dans un fichier ou une variable

    en fait c'est pour faire un programme qui lance en permanence quatres commandes du meme type et que dès que l'une des quatres se termine, en lance un autre.
    merc d'avance

  2. #2
    Expert éminent
    Avatar de Michaël
    Profil pro
    Ingénieur systèmes et réseaux
    Inscrit en
    Juillet 2003
    Messages
    3 497
    Détails du profil
    Informations personnelles :
    Âge : 37
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Ingénieur systèmes et réseaux

    Informations forums :
    Inscription : Juillet 2003
    Messages : 3 497
    Points : 8 239
    Points
    8 239
    Par défaut
    salut,
    as-tu regardé du coté des threads ? il existe de nombreuses fonctions permettant de faire un tas de choses sur les pid, users, etc. il y a la lib pthread qui pourrait faire cela

  3. #3
    Membre à l'essai
    Profil pro
    Inscrit en
    Septembre 2006
    Messages
    39
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Septembre 2006
    Messages : 39
    Points : 13
    Points
    13
    Par défaut
    heu je suis en train de chercher la doc. j'ai vu qu'il y avais un paquet libpthread-dev mais pas moyen de trouver la doc. et le site du projet semble vide et tout neuf alors que sur certains sites ils disent que libpthreads existe depuis 1996

    je regardes du coté de la glib. ca a l'air intéréssant !

  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
    Points : 28 121
    Points
    28 121
    Par défaut
    Bonjour,

    Oublie les threads et tout ca.. unistd.h est ton amie ! Issu du man de getpid() :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
         #include <unistd.h>
     
         pid_t getpid(void);
     
         pid_t getpgrp(void);
     
         pid_t getppid(void);
     
         pid_t getpgid(pid_t pid);
    "La route est longue, mais le chemin est libre" -- https://framasoft.org/
    Les règles du forum

  5. #5
    Membre confirmé Avatar de Lunixinclar
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Juillet 2006
    Messages
    416
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Ingénieur développement logiciels
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Juillet 2006
    Messages : 416
    Points : 489
    Points
    489
    Par défaut
    pid = fork();

  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
    Points : 28 121
    Points
    28 121
    Par défaut
    Mea culpa, avais pas vu que tu voulais lancer un process, puis récupérer son pid.

    Donc oui, fork() est ton amie (merci Linuxinclar)
    "La route est longue, mais le chemin est libre" -- https://framasoft.org/
    Les règles du forum

  7. #7
    Membre à l'essai
    Profil pro
    Inscrit en
    Septembre 2006
    Messages
    39
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Septembre 2006
    Messages : 39
    Points : 13
    Points
    13
    Par défaut
    j'ai essayé de comprendre les threads et c'est d'un compliqué !!! les exemples de la glib utilisent des mots clefs dont j'ingnorais l'existence et en plus il leur faut une bonne centaine de lignes pour l'exemple le plus "simple"
    merci quand meme Michael mais mes 20 heures de cours de C et ma pratique personnelle depuis 2ans ne suffisent pas
    je regardes la methode fork().

    edit:
    si j'ai bien compris, fork() renvoie le pid du programme dans laquelle elle est lancée. je ne vois pas trop comment ca pourait m'etre utile ?
    en admetant que fork() crée un processus fils et qu'il renvoie le pid du fils, comment je peu faire pour lancer un "wget http://url.com/texte1.txt".
    je ne voie pas trop bien a quoi peu servir le processus fils si on ne lui a rien demandé.

  8. #8
    Expert éminent
    Avatar de PRomu@ld
    Homme Profil pro
    Ingénieur de Recherche
    Inscrit en
    Avril 2005
    Messages
    4 155
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 38
    Localisation : France, Vienne (Poitou Charente)

    Informations professionnelles :
    Activité : Ingénieur de Recherche
    Secteur : Enseignement

    Informations forums :
    Inscription : Avril 2005
    Messages : 4 155
    Points : 6 486
    Points
    6 486
    Par défaut
    si j'ai bien compris, fork() renvoie le pid du programme dans laquelle elle est lancée. je ne vois pas trop comment ca pourait m'etre utile ?
    fork duplique le processus courant, c'est à dire que tu vas te retrouver avec deux processus qui vont éxécuter le même code. (tout est copié : le code, la pile, le tas, l'endroit ou tu es dans le programme)

    L'idée est de recouvrir un des deux processus pour pouvoir exécuter une commande en parallèle.

    Le fork se passe comme ceci:

    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;
     
    pid = fork();
     
    if ( pid == -1 )
    {
         /* il y a eu une erreur dans le fork */
    }
     
    if( pid == 0 )
    {
         /* ici tu as le code qui va s'éxécuter dans le fils */
    }
    else
    {
         /* ici c'est le code qui va s'éxécuter dans le père */
    }
    L'idée est donc qu'une fois que tu as fait un fork, tu as deux processus, la seule manière de les différencier est d'utiliser la valeur de retour du fork, elle vaut 0 dans le cas du fils et vaut une valeur suppérieure à 0 pour le père, cette valeur est le pid du fils. Ca vaut aussi -1 si le fork n'a pas eu lieu.

    Une fois que tu es dans le code du fils, il faut que tu utilises une fonction de la famille exec* afin d'éxécuter une autre commande.

    ensuite, pour gérer la bonne terminaison des fils il faut utiliser les fonctions wait* .

  9. #9
    Membre à l'essai
    Profil pro
    Inscrit en
    Septembre 2006
    Messages
    39
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Septembre 2006
    Messages : 39
    Points : 13
    Points
    13
    Par défaut
    Merci de ton aide.
    je crois avoir compris:
    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
    pid = fork();
     
    if ( pid == -1 )
    {
         /* il y a eu une erreur dans le fork */
    }
    while(1)
    {
    if( pid == 0 )
    {
         int pid_fils = getpid()
         /* ici tu as le code qui va s'éxécuter dans le fils */
    }
    else
    {
         int pid_pere = getpid()
         /* ici c'est le code qui va s'éxécuter dans le père */
    }
    }
    dans la boucle, c'est soit le code fils qui est executé soit le code père. j'imagine que la valeur du pid est modifié en interne en fonction du processus actif (0 pour le fils et getpid() pour le père) et que meme si ce n'est pas visible, ca dois l'etre en assembleur. ou sinon c'est lors de la manip "pid == 0" que le pid switch entre 0 et le pid père.

    enfin c'est un peu conffus dans ma tete mais c'etait pire hier. je vais tester avec gcc. merci

    ah oui, j'ai trouvé un peu de doc : http://www.cs.cf.ac.uk/Dave/C/node22.html

  10. #10
    Expert éminent
    Avatar de PRomu@ld
    Homme Profil pro
    Ingénieur de Recherche
    Inscrit en
    Avril 2005
    Messages
    4 155
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 38
    Localisation : France, Vienne (Poitou Charente)

    Informations professionnelles :
    Activité : Ingénieur de Recherche
    Secteur : Enseignement

    Informations forums :
    Inscription : Avril 2005
    Messages : 4 155
    Points : 6 486
    Points
    6 486
    Par défaut
    j'imagine que la valeur du pid est modifié en interne en fonction du processus actif
    En fait, tu as deux processus, c'est le noyau qui attribue les pid aux processus lors de leur création, il n'y a aucune manip bizarre là dessous.

  11. #11
    Membre à l'essai
    Profil pro
    Inscrit en
    Septembre 2006
    Messages
    39
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Septembre 2006
    Messages : 39
    Points : 13
    Points
    13
    Par défaut
    ben je viens de tester ca et c'est marant, les deux parities du if s'éxecutent !
    int main(int* argc, char** argv)
    {

    pid_t pid;
    pid = fork();
    char *args[10];
    args[0] = NULL;
    if(pid == -1) { std::cerr << "impossible de forker\n"; exit(0); }
    if(pid == 0)
    {
    std::cout << "prog fils\n";
    execvp("df",args);
    }
    else
    {
    std::cout << "prog pere\n";
    }
    return 0;
    }
    c'a maffiche :
    prog fils
    Sys. de fich. 1K-blocs Occupé Disponible Capacité Monté sur
    /dev/hda5 3842376 2584620 1062568 71% /
    udev 10240 72 10168 1% /dev
    devshm 323304 0 323304 0% /dev/shm
    /dev/hda8 1829159 236295 1495271 14% /home
    /dev/hda9 24628376 13695604 9681712 59% /mnt/data
    /dev/hda6 3842376 73248 3573940 3% /mnt/disto
    /dev/hda1 3896128 4 3896124 1% /windows
    prog pere
    donc en fait le if ce n'est pas un test vu que les deux parties s'éxécutent, mais un moyen synthaxique de séparer le traitement des deux processus

    c'est tout bon ! ca marche parfaitement. j'ai juste un dernier problème, c'est que j'ai beau rediriger ma commande dans /dev/null, elle s'affiche quand meme dans mon terminal.
    la sortie de mon programme ce mélange avec la sortie de la commande que je lance (4fois en plus).
    c'est le bordel

  12. #12
    Rédacteur/Modérateur

    Avatar de gorgonite
    Homme Profil pro
    Ingénieur d'études
    Inscrit en
    Décembre 2005
    Messages
    10 322
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 39
    Localisation : France

    Informations professionnelles :
    Activité : Ingénieur d'études
    Secteur : Transports

    Informations forums :
    Inscription : Décembre 2005
    Messages : 10 322
    Points : 18 681
    Points
    18 681
    Par défaut
    Citation Envoyé par klipper
    donc en fait le if ce n'est pas un test vu que les deux parties s'éxécutent, mais un moyen synthaxique de séparer le traitement des deux processus

    ben si... c'est que chaque partie est exécutée dans un process différent
    (sauf le cas d'erreur )
    Evitez les MP pour les questions techniques... il y a des forums
    Contributions sur DVP : Mes Tutos | Mon Blog

  13. #13
    Expert éminent
    Avatar de PRomu@ld
    Homme Profil pro
    Ingénieur de Recherche
    Inscrit en
    Avril 2005
    Messages
    4 155
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 38
    Localisation : France, Vienne (Poitou Charente)

    Informations professionnelles :
    Activité : Ingénieur de Recherche
    Secteur : Enseignement

    Informations forums :
    Inscription : Avril 2005
    Messages : 4 155
    Points : 6 486
    Points
    6 486
    Par défaut
    donc en fait le if ce n'est pas un test
    Euh, si quand même .

    mais un moyen synthaxique de séparer le traitement des deux processus
    Non, c'est toujours un test qui permet de différencier ce qui est éxécuté par le père et ce qui est éxécuté par le fils, étant donné que le fork duplique le code.

    Ce que tu ne peux pas savoir, c'est l'ordre dans lequel sont éxécutés les processus (le fils peut s'éxécuter avant le père et inversement).

  14. #14
    Membre à l'essai
    Profil pro
    Inscrit en
    Septembre 2006
    Messages
    39
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Septembre 2006
    Messages : 39
    Points : 13
    Points
    13
    Par défaut
    houla !!
    quand on met du code en dehors du test, style comme ca
    int main(int* argc, char** argv)
    {

    pid_t pid;
    pid = fork();
    char *args[10];
    args[0] = NULL;
    if(pid == -1) { std::cerr << "impossible de forker\n"; exit(0); }
    if(pid == 0)
    {
    std::cout << "prog fils\n";
    execvp("df",args);
    }
    else
    {
    std::cout << "prog pere\n";
    }
    //et la on met tout plein de code !
    std::cout << "ce texte bien affiché par le programme père non \? c'est comme s'il etait dans le \"else\" ";
    return 0;

  15. #15
    Rédacteur/Modérateur

    Avatar de gorgonite
    Homme Profil pro
    Ingénieur d'études
    Inscrit en
    Décembre 2005
    Messages
    10 322
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 39
    Localisation : France

    Informations professionnelles :
    Activité : Ingénieur d'études
    Secteur : Transports

    Informations forums :
    Inscription : Décembre 2005
    Messages : 10 322
    Points : 18 681
    Points
    18 681
    Par défaut
    ben non, ce qui est après le else est exécuté par les deux... donc souvent on ne met rien
    Evitez les MP pour les questions techniques... il y a des forums
    Contributions sur DVP : Mes Tutos | Mon Blog

  16. #16
    Membre confirmé Avatar de Lunixinclar
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Juillet 2006
    Messages
    416
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Ingénieur développement logiciels
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Juillet 2006
    Messages : 416
    Points : 489
    Points
    489
    Par défaut
    Maintenant il faut passer à l' étape suivante avec waitpid() et WIFEXITED().
    Go.

    PS: Ton prof de programmation système est souvent absent ou quoi??

  17. #17
    Membre à l'essai
    Profil pro
    Inscrit en
    Septembre 2006
    Messages
    39
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Septembre 2006
    Messages : 39
    Points : 13
    Points
    13
    Par défaut
    actuellement, je fais ca et ca semble fonctionner :
    int main(int* argc, char** argv)
    {
    int i;
    pid_t pid[4];
    pid_t pid_fils[4];
    //la je crée 4 fils
    for(i=0; i<4; i++)
    {
    pid[i] = fork();
    if(pid == 0)
    {
    execvp(....)
    }
    else
    {
    pid_fils[i] = pid[i];
    }
    }
    //et la je relance si l'un d'eux s'arrete
    pid_t pid2
    while(1)
    {
    int codesortie;
    pid2 = wait(&codesortie);
    for(i=0; i<4; i++)
    {
    if(pid_fils[i] == pid2)
    {
    pid[i]=fork();
    if(pid[i]==0)
    {
    execvp(...);
    }
    else
    {
    pid_fils[i]=pid[i];
    }
    }
    }
    }
    }
    le problème c'est que je fork n fois (en général 4 fois) pour avoir trois threads simultanés. et des que l'un d'eux se termine, j'en relance un autre.

  18. #18
    Expert éminent
    Avatar de PRomu@ld
    Homme Profil pro
    Ingénieur de Recherche
    Inscrit en
    Avril 2005
    Messages
    4 155
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 38
    Localisation : France, Vienne (Poitou Charente)

    Informations professionnelles :
    Activité : Ingénieur de Recherche
    Secteur : Enseignement

    Informations forums :
    Inscription : Avril 2005
    Messages : 4 155
    Points : 6 486
    Points
    6 486
    Par défaut
    le problème c'est que je fork n fois (en général 4 fois) pour avoir trois threads simultanés. et des que l'un d'eux se termine, j'en relance un autre.
    un thread et un processus sont deux choses différentes !

    Sinon, je ne vois pas ton problème, il faudrait que tu explique exactement ce que tu voudrais obtenir.

  19. #19
    Membre à l'essai
    Profil pro
    Inscrit en
    Septembre 2006
    Messages
    39
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Septembre 2006
    Messages : 39
    Points : 13
    Points
    13
    Par défaut
    ben en fait ya pas de problème, ca semble fonctionner.
    ce que je veux faire, c'est un programme pour envoyer quatre fichiers à la fois sur un serveur ftp ou nntp.
    mais le code si dessous montre que tout ce qui est en dehors du "if(pid==0)" ne s'éxecute que dans le père :
    int main(int* argc, char** argv)
    {
    char *args[60];
    char *args_tmp[20];
    args_tmp[0] = strdup("sleep");
    args_tmp[1] = strdup("10");
    args_tmp[2] = NULL;

    int i;
    pid_t pid[4];
    pid_t son_pid_id[4];

    for(i=0; i<4; i++)
    {
    pid[i] = fork();
    if(pid[i] == -1) { std::cerr << "unable to fork\n"; return 1; }
    if(pid[i] == 0)
    {
    execvp(args_tmp[0],args_tmp);
    std::cout << "fils numéro " << i << "\n"; //cette ligne ne s'affiche jamais
    }
    else
    {
    std::cout << "père numéro " << i << "mon pid est " << getpid() << " , mon fils est " << pid[i] << "\n";
    }


    std::cout << "en dehors du if else le pid est de " << getpid() << "\n";
    }
    std::cout << "en dehors de la boucle le pid est de " << getpid() << "\n";
    args_tmp[1] = strdup("20");
    execvp(args_tmp[0],args_tmp);
    return 0;
    }
    et en faisant un ps aux juste apres avoir lancé le prog :
    thomas 1246 0.0 0.0 2972 476 pts/1 S+ 18:00 0:00 sleep 20
    thomas 1247 0.0 0.0 2972 476 pts/1 S+ 18:00 0:00 sleep 10
    thomas 1248 0.0 0.0 2972 476 pts/1 S+ 18:00 0:00 sleep 10
    thomas 1249 0.0 0.0 2968 472 pts/1 S+ 18:00 0:00 sleep 10
    thomas 1250 0.0 0.0 2968 472 pts/1 S+ 18:00 0:00 sleep 10
    ou le pid du père est 1246.

    donc tout roule, je pense avoir pigé. reste ce problème d'affichage (toutes les commandes envoie leur sortie sur mon terminal pas moyen de les cacher !

Discussions similaires

  1. Réponses: 5
    Dernier message: 31/05/2006, 19h30
  2. [C#] Lancer une commande systeme ?
    Par Oberown dans le forum Windows Forms
    Réponses: 1
    Dernier message: 25/07/2005, 11h29
  3. [Dos] Lancer une commande dos sans attendre la fin
    Par MrEddy dans le forum Windows
    Réponses: 4
    Dernier message: 09/06/2005, 17h38
  4. Lancer une commande en C.
    Par ronan99999 dans le forum Windows
    Réponses: 2
    Dernier message: 26/07/2004, 16h25
  5. Réponses: 1
    Dernier message: 30/04/2004, 11h36

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