web-dev-qa-db-fra.com

Utilisation du canal pour passer des valeurs entières entre le parent et l'enfant

Je suis un peu confus sur la façon d'utiliser correctement pipe () pour passer des valeurs entières entre deux processus.

Dans mon programme, je crée d'abord une pipe, puis je la fourche. Je suppose que j'ai "deux" tuyaux alors?

D'après ce que je comprends, c'est ma mission. Mon parent passe par une boucle for vérifiant une valeur entière "i" pour une certaine opération, augmente une variable de comptage et enregistre la valeur dans un tableau. Après chaque vérification, mon parent doit transmettre une valeur entière, "i" à mon enfant via un canal. Mon enfant utilise ensuite cette valeur entière, vérifie la valeur et devrait augmenter une variable de comptage et enregistrer le résultat dans un tableau [partagé?]. Finalement; l'enfant doit retourner son décompte final au parent, qui imprime ensuite les deux décomptes et le tableau "Partagé".

-> Je ne suis pas sûr d'avoir besoin d'un tableau partagé ou de sauvegarder les résultats. Je n'ai peut-être besoin que des comptes - les devoirs étaient ambigus et j'attends une réponse du professeur. Aussi; puis-je même faire un tableau partagé entre les processus? Cela ressemble à un début de problème pour moi.

-> Voici mes questions: une; comment utiliser les canaux pour les entiers? Je ne les ai vus que pour les tableaux de caractères et les réponses précédentes ne semblent pas penser que c'est possible ou légal ..? Je ne suis pas sûr. Je n'ai trouvé aucune résolution à ce sujet.

-> Comment utiliser un canal unidirectionnel pour transmettre des entiers à un enfant? Et l'enfant doit-il retourner quelque chose? Je ne sais pas comment je peux ... faire la différence entre les deux tuyaux. Je "sais" [ou je pense savoir] que je dois fermer une portion inutilisée de chaque tuyau pour éviter "un vague problème".

Désolé pour les questions stupides; Je n'ai pas encore appris de processus (à part la fourche) ou de tuyaux (du tout) dans cette classe - donc je ne sais pas vraiment par où commencer!

Voici des parties de mon code - ce n'est pas joli et cela ne fonctionne pas et je ne m'attends pas à ce que ce soit le cas. Il s'agit plutôt d'un espace réservé Shell. Une fois que j'aurais compris comment utiliser un tuyau - je donnerais probablement du sens au code.

int main(void)
{
int fd[2];
pid_t childpid;
pid_t parentpid;
int i;
int threecount = 0;
int fivecount = 0;;
int results [MAXSIZE];

parentpid = getpid(); //Get current process ID number

pipe(fd);
childpid = fork(); 

if(childpid == 0){
close(fd[0]); //Closing this for some other reason

}
int j = 0;

if(childpid > 0)
close(fd[1]); //Closing this for some reason


if( childpid == -1 )
{
    perror("Failed to fork\n");
    return 1;
}
if (childpid > 0)
{
    for(i = 1; i < MAXSIZE;i++)
    {
        if(i % 5 == 0)
        {
            fivecount++;
            i = results[j];
            j++; 
            wait(NULL);
        }
    }
}
else if (childpid == 0)
    {
        if(i % 3 == 0) //This i here should probably be the i value above, piped to the child
        {
            threecount++;
            i = results[j];  //This should be part of th pipe
            j++;    //Trying to keep count of that shared array, not really the right way to do it though.
        }

    }
    printf("%d  %d  \n", fivecount,threecount);
    return 0;

}

17
user1741874

C'est à peu près aussi boiteux (et pas de vérification d'erreur, btw) un échantillon que je peux rassembler pour utiliser un canal pour envoyer un int d'un parent à un processus enfant, où l'enfant a été lancé à partir de fork (). Cela devient plus compliqué (évidemment) pour envoyer et recevoir des données, mais je ne peux pas tout faire pour vous. Cela forks juste et attend un int (en fait, le nombre d'octets qui sont utilisés par un int) de l'enfant.

pdate: Ajout d'un exemple de communication bidirectionnelle send + response après celui-ci. Voir la deuxième liste de codes pour plus d'informations.

J'espère que cela aide.

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>

int main(int argc, char *argv[])
{
    int fd[2];
    int val = 0;

    // create pipe descriptors
    pipe(fd);

    // fork() returns 0 for child process, child-pid for parent process.
    if (fork() != 0)
    {
        // parent: writing only, so close read-descriptor.
        close(fd[0]);

        // send the value on the write-descriptor.
        val = 100;
        write(fd[1], &val, sizeof(val));
        printf("Parent(%d) send value: %d\n", getpid(), val);

        // close the write descriptor
        close(fd[1]);
    }
    else
    {   // child: reading only, so close the write-descriptor
        close(fd[1]);

        // now read the data (will block)
        read(fd[0], &val, sizeof(val));
        printf("Child(%d) received value: %d\n", getpid(), val);

        // close the read-descriptor
        close(fd[0]);
    }
    return 0;
}

Production:

Parent(5943) send value: 100
Child(5945) received value: 100

Mise à jour: Développé pour inclure l'envoi + la réponse en utilisant deux jeux de tuyaux

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/wait.h>

// some macros to make the code more understandable
//  regarding which pipe to use to a read/write operation
//
//  Parent: reads from P1_READ, writes on P1_WRITE
//  Child:  reads from P2_READ, writes on P2_WRITE
#define P1_READ     0
#define P2_WRITE    1
#define P2_READ     2
#define P1_WRITE    3

// the total number of pipe *pairs* we need
#define NUM_PIPES   2

int main(int argc, char *argv[])
{
    int fd[2*NUM_PIPES];
    int val = 0, len, i;
    pid_t pid;

    // create all the descriptor pairs we need
    for (i=0; i<NUM_PIPES; ++i)
    {
        if (pipe(fd+(i*2)) < 0)
        {
            perror("Failed to allocate pipes");
            exit(EXIT_FAILURE);
        }
    }

    // fork() returns 0 for child process, child-pid for parent process.
    if ((pid = fork()) < 0)
    {
        perror("Failed to fork process");
        return EXIT_FAILURE;
    }

    // if the pid is zero, this is the child process
    if (pid == 0)
    {
        // Child. Start by closing descriptors we
        //  don't need in this process
        close(fd[P1_READ]);
        close(fd[P1_WRITE]);

        // used for output
        pid = getpid();

        // wait for parent to send us a value
        len = read(fd[P2_READ], &val, sizeof(val));
        if (len < 0)
        {
            perror("Child: Failed to read data from pipe");
            exit(EXIT_FAILURE);
        }
        else if (len == 0)
        {
            // not an error, but certainly unexpected
            fprintf(stderr, "Child: Read EOF from pipe");
        }
        else
        {
            // report what we received
            printf("Child(%d): Received %d\n", pid, val);

            // now double it and send it back
            val *= 2;

            printf("Child(%d): Sending %d back\n", pid, val);
            if (write(fd[P2_WRITE], &val, sizeof(val)) < 0)
            {
                perror("Child: Failed to write response value");
                exit(EXIT_FAILURE);
            }
        }

        // finished. close remaining descriptors.
        close(fd[P2_READ]);
        close(fd[P2_WRITE]);

        return EXIT_SUCCESS;
    }

    // Parent. close unneeded descriptors
    close(fd[P2_READ]);
    close(fd[P2_WRITE]);

    // used for output
    pid = getpid();

    // send a value to the child
    val = 42;
    printf("Parent(%d): Sending %d to child\n", pid, val);
    if (write(fd[P1_WRITE], &val, sizeof(val)) != sizeof(val))
    {
        perror("Parent: Failed to send value to child ");
        exit(EXIT_FAILURE);
    }

    // now wait for a response
    len = read(fd[P1_READ], &val, sizeof(val));
    if (len < 0)
    {
        perror("Parent: failed to read value from pipe");
        exit(EXIT_FAILURE);
    }
    else if (len == 0)
    {
        // not an error, but certainly unexpected
        fprintf(stderr, "Parent(%d): Read EOF from pipe", pid);
    }
    else
    {
        // report what we received
        printf("Parent(%d): Received %d\n", pid, val);
    }

    // close down remaining descriptors
    close(fd[P1_READ]);
    close(fd[P1_WRITE]);

    // wait for child termination
    wait(NULL);

    return EXIT_SUCCESS;
}

(compiler avec, par exemple, gcc thisfile.c -o test)

Sortie

Parent(2794): Sending 42 to child
Child(2797): Received 42
Child(2797): Sending 84 back
Parent(2794): Received 84
25
WhozCraig