管道和select()有问题

时间:2009-12-06 21:10:20

标签: c pipe fork select-function

我似乎遇到了管道和选择问题。

上下文:必须对shell执行的内容进行编程:
logn [--tick n] cmd [args] [,cmd [args]] ...

基本上,这是一个多程序同时发生的程序。

约束:每个输出行必须以printf“%d:%s”格式的前面的命令编号开头 即:

0: first line of first command.  
0: second line of first command.  
1: first line of second command.  
0: third line of first command.  
1: second line of second command.  

如果已指定勾选,如果n秒内未发送输出,系统将打印一个句点。 必须使用select() 如果最后一个输出是句点,则系统不会打印另一个句号。

问题:

  1. 第二个命令的输出似乎转到第一个管道的p [0] 当我读入p [0] [0]时,我得到发送到p [1] [0]的内容。 p [1] [0]中似乎没有任何内容。

  2. 每当我的选择超时时,它似乎都会卡在那里。

  3. 我之前问了一个问题,所以看起来很熟悉。由于问题不同,我发了一个新帖子。这篇老帖子让我很难弄清楚分叉。

    这是我的代码:

    #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"
    
    /* Fetches the number of commands in parameters. Number of Commas + 1 */
    int getNbCmd(char ** argv)
    {
        int nbCmd = 1;
        int i = 0;    
        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(indexArgv < argc)
        {
            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(argc > 3)
        {
            if(strcmp(argv[1], "--tick") == 0)
                tick = atoi(argv[2]);
        }
    
        getCommandes(tbCmd, argc, argv);
    
        int i,j;
    
        pid_t pidM[nbCmds];    
        int p[nbCmds][2];
    
        for (i = 0;i < nbCmds;i++)
        {            
            if ( pipe( p[i] ) != 0 ){ perror( "pipe()" ); exit(1); }
        }
    
        for (i = 0;i < nbCmds;i++)
        {    
            // fork() to get child process        
            pidM[i] = fork();    
    
            if ( pidM[i] < 0 ){ perror( "fork()" ); exit(1); }
            //Child Processing
            else if (pidM[i] == 0)
            {
                close(p[i][0]);
                dup2(p[i][1], STDOUT_FILENO);
    
                int ret;
                ret = execvp(tbCmd[i][0], tbCmd[i]);
                perror("execvp()");
            }
        }
    
        // Parent Processing
        for (i = 0;i < nbCmds;i++)
        {
            close(p[i][1]);
        }
    
        char * buffer;
        int retval = 1;
        int boolAfficher = 0;
        int nbNull = 0;        
    
        fd_set set;
        struct timeval timeout;
    
        /* Initialize the file descriptor set. */
        FD_ZERO (&set);
        for (i = 0;i < nbCmds;i++)
        {
            FD_SET (p[i][0], &set);            
        }
    
        while(nbNull < nbCmds)
        {
            if(tick >= 0)
            {
                timeout.tv_sec = (unsigned int)tick;
                timeout.tv_usec = 0;
                retval = select (FD_SETSIZE,&set, NULL, NULL, &timeout);                
            }
            else
                retval = select (FD_SETSIZE,&set, NULL, NULL, NULL);
    
            if(retval == 0)
            {
                if(boolAfficher == 0 && tick >= 0)
                {
                    printf(".\n");
                    boolAfficher = 1;
                }                
            }
            else if(retval > 0)
            {            
                for (i = 0;i < nbCmds;i++)
                {
                    if(FD_ISSET(p[i][0], &set))
                    {
                        buffer = readline(p[i][0]);
                        if(buffer[0] != '\0')
                        {
                            printf("%d: %s", i, buffer);
                        }
                        else
                        {
                            FD_CLR(p[i][0], &set);                            
                            nbNull++;
                        }
                    }
                    else
                        printf("Not ISSET[%d]\n", i);
    
                    free(buffer);
                }                
            }
            else
                perror("select()");
        }
    
        wait(NULL);
        free(tbCmd);
        exit(0);
    }
    

1 个答案:

答案 0 :(得分:1)

我能搞清楚了!

在递归调用logn

时仍然有错误

I.e:./logn --tick 2 ./logn --tick 2 ./cmd1 0 un 6 deux,。/ logn --tick 2 ./cmd1 1 trois 6 quatre

./cmd1的代码

while test "x$#" != "x0"; do
    sleep $1
    shift
    test "x$#" != "x0" || exit
    echo $1
    shift
done

以下是我的固定代码,以防任何人感兴趣:

#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"

/* Fetches the number of commands in parameters. Number of Commas + 1 */
int getNbCmd(char ** argv)
{
    int nbCmd = 1;
    int i = 0;    
    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(indexArgv < argc)
    {
        if(strcmp(argv[indexArgv], "--tick") == 0)
            indexArgv = 3;
    }

    while (argv[indexArgv] != '\0')
    {
        if(strcmp(argv[indexArgv], ",") == 0)
        {

            cmd[indexCmd] = (char *) 0;
            tbCmd[indexTbCmd] = 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(argc > 3)
    {
        if(strcmp(argv[1], "--tick") == 0)
            tick = atoi(argv[2]);
    }

    getCommandes(tbCmd, argc, argv);

    int i,j;        

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

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

    for (i = 0;i < nbCmds;i++)
    {    
        // fork() to get child process        
        pidM[i] = fork();    

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

            ret = execvp(tbCmd[i][0], tbCmd[i]);
            perror("execvp()");
            _exit(1);
        }
    }

    // Parent Processing

    for (i = 0;i < nbCmds;i++)
    {
        close(p[i][1]);
    }

    char * buffer = NULL;        
    int retval = 1;
    int boolAfficher = 0;

    int nbNull = 0;
    int isOk[nbCmds];

    for (i = 0;i < nbCmds;i++)
    {
        isOk[i] = 1;
    }

    fd_set set;
    struct timeval timeout;

    while(nbNull < nbCmds)
    {
        FD_ZERO (&set);
        for (i = 0;i < nbCmds;i++)
        {    
            if(isOk[i] == 1)
                FD_SET (p[i][0], &set);
        }

        if(tick > 0)
        {
            timeout.tv_sec = (unsigned int)tick;
            timeout.tv_usec = 0;
            retval = select (FD_SETSIZE,&set, NULL, NULL, &timeout);                
        }
        else
        {
            timeout.tv_sec = 0;
            timeout.tv_usec = 0;
            retval = select (FD_SETSIZE,&set, NULL, NULL, &timeout);      
        }

        if(retval == 0)
        {
            if(boolAfficher == 0 && tick >= 0)
            {
                printf(".\n");
                boolAfficher = 1;
            }                    
        }
        else
        {
            for (i = 0;i < nbCmds;i++)
            {
                if(FD_ISSET(p[i][0], &set))
                {                            
                    buffer = readline(p[i][0]);
                    if(buffer[0] != '\0')
                    {
                        printf("%d: %s", i, buffer);
                        boolAfficher = 0;
                    }
                    else
                    {
                        isOk[i] = 0;
                        nbNull++;
                    }
                    free(buffer);
                }
            }
        }
    }

    wait(NULL);
    free(tbCmd);
    exit(0);
}