Потерянный в Многократной Вилке (), Трубе () и Выберите () - PullRequest
2 голосов
/ 05 декабря 2009

Надеюсь, я смогу найти здесь какую-то помощь, потому что я начинаю сдаваться. Поднимите голову, так как это домашнее задание, поэтому оно может быть глупым.

Контекст: Должно быть запрограммировано что-то, что будет выполнено так:
logn [--tick n] cmd [args] [, cmd [args]] ...

По сути, это программа, которая одновременно выполняет несколько программ.

Ограничения: Каждая строка вывода должна начинаться с номера команды впереди в формате printf "% d:% s" то есть: 0: первая строка первой команды.
0: вторая строка первой команды.
1: первая строка второй команды.
0: третья строка первой команды.
1: вторая строка второй команды.

Если галочка была указана, система напечатает точку, если в течение n секунд не было отправлено ни одного сообщения.
Необходимо использовать Select ()
Если последний вывод был периодом, система не печатает другой период.

Теперь вот моя проблема! Я смог заставить его работать с помощью одной команды. В тот момент, когда я пытаюсь сделать это несколько команд, я, кажется, не удается. Я считаю, что это может быть моим подходом. Может быть, некоторые из вас смогут мне помочь.

Вот то, что я пытался сделать для Multiple Cmd. Возможно, я совершенно неправ, поэтому мне нужна помощь:

#include <string.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <errno.h>
#include <sys/types.h>
#include <sys/time.h> 
#include "readline.h"

// Reference: http://www.gnu.org/s/libc/manual/html_node/Waiting-for-I_002fO.html
int input_timeout (int filedes, unsigned int seconds)
{
    fd_set set;
    struct timeval timeout;

    /* Initialize the file descriptor set. */
    FD_ZERO (&set);
    FD_SET (filedes, &set);

    /* Initialize the timeout data structure. */
    timeout.tv_sec = seconds;
    timeout.tv_usec = 0;

    /* select returns 0 if timeout, 1 if input available, -1 if error. */
    return (select (FD_SETSIZE,&set, NULL, NULL, &timeout));
}

/* Fetches the number of commands in parameters. Number of Commas + 1 */
int getNbCmd(char ** argv)
{
    int nbCmd = 1;
    int i;    
    while(argv[i] != '\0')
    {        
        if(strcmp(argv[i], ",") == 0)
            nbCmd++;
        i++;
    }

    return nbCmd;
}


/* Fills the Command Array */
void getCommandes(char *** tbCmd, int argc, char ** argv)
{    
    int indexArgv = 1;
    int indexCmd = 0;
    int indexTbCmd = 0;        

    char ** cmd = (char **)malloc(argc*sizeof(char *));

    if(strcmp(argv[indexArgv], "--tick") == 0)
        indexArgv = 3;

    while (indexArgv < argc)
    {

        if(strcmp(argv[indexArgv], ",") == 0)
        {    
            cmd[indexCmd] = (char *) 0;
            tbCmd[indexTbCmd] = cmd;
            free(cmd);
            cmd = (char **)malloc(argc*sizeof(char *));

            indexTbCmd++;
            indexCmd = 0;
        }
        else
        {
            char * arg;
            arg = argv[indexArgv];
            cmd[indexCmd] = arg;        

            indexCmd++;
        }
        indexArgv++;
    }

    cmd[indexCmd] = (char *) 0;
    tbCmd[indexTbCmd] = cmd;
    free(cmd);        
}


int main (int argc, char ** argv)
{
    int nbCmds = getNbCmd(argv);    
    int tick = -1;    

    char *** tbCmd = (char ***) malloc (nbCmds*sizeof(char **));

    if(strcmp(argv[1], "--tick") == 0)
        tick = atoi(argv[2]);

    getCommandes(tbCmd, argc, argv);

    int i;

    pid_t pidM[nbCmds];    
    int p[nbCmds][2];

    for (i = 0;i < nbCmds;i++)
    {            
        if ( pipe( p[i] ) != 0 ){ perror( "pipe()" ); exit(1); }

        // fork() to get child process        
        pidM[i] = fork();    

        if ( pidM[i] < 0 ){ perror( "fork()" ); exit(1); }
        else if (pidM[i] == 0)
        {
            close(p[i][0]);
            dup2(p[i][1], STDOUT_FILENO);    

            int ret;
            ret = execvp(tbCmd[i][0], tbCmd[i]);            
        }
        else
        {
            close(p[i][1]);

            char * buffer;
            int retval = 1;
            int pntAfficher = 0;  //Boolean for Period Printing
            /* select returns 0 if timeout, 1 if input available, -1 if error. */
            if(tick >= 0)
                retval = input_timeout(p[i][0], tick);
            if (retval == 0 && pntAfficher == 0)
            {
                printf(".\n");
                pntAfficher = 1;
            }

            buffer = readline(p[i][0]);
            while(buffer[0] != '\0')
            {                
                printf("%d: %s",i, buffer);
                free(buffer);

                /* select returns 0 if timeout, 1 if input available, -1 if error. */
                if(tick >= 0)
                    retval = input_timeout(p[i][0], tick);
                if (retval == 0 && pntAfficher == 0)
                {
                    printf(".\n");
                    pntAfficher = 1;
                }
                buffer = readline(p[i][0]);
                pntAfficher = 0;

            free(buffer);
            }
        }
    }
free(tbCmd);

}

Ответы [ 2 ]

2 голосов
/ 05 декабря 2009

Вам нужно разветвить все дочерние элементы в цикле, а затем во втором цикле прочитать все данные из всех дочерних элементов.

Вы хотите слушать вывод всех детей параллельно (именно это select делает для вас), но все дети должны быть запущены, чтобы это работало. Ваша текущая петля for порождает ребенка, затем переходит к select ... что не подходит для него.

1 голос
/ 05 декабря 2009

Не совсем уверен, что вы имеете в виду, когда говорите «похоже, не получается», но похоже, что вам нужно изменить свой код, чтобы слушать ВСЕХ своих детей. Для этого можно использовать select, просто посмотрите на человека select и попробуйте добавить несколько FD, используя FD_SET

...