管道和 select() 遇到问题

发布于 2024-08-13 05:55:32 字数 4850 浏览 9 评论 0原文

我似乎在管道和选择方面遇到了麻烦。

上下文:必须编写一些将由 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. 每当我的选择遇到超时,它似乎就会卡在那里。

我之前问过一个问题,所以看起来可能很熟悉。由于问题不同,我发了一个新帖子。旧帖子帮助我弄清楚了分叉。

这是我的代码:

#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);
}

I seem to be having trouble with pipe and select.

Context: Have to program something which will be shell executed as such:
logn [--tick n] cmd [args] [, cmd [args]]...

Basically, it's a program that multiple programs simultanously.

Constraints: Each output line has to start with it's command number in front in format printf "%d: %s"
ie:

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.  

If the tick has been specified, system will print a period if no output has been sent for n seconds.
Must use select()
If the last output was a period, system does not print another period.

Issues:

  1. It seems the output of the second command goes to the p[0] of the first pipe.
    When I read into p[0][0] i get what was sent to p[1][0]. there doesn't seem to be anything in p[1][0].

  2. Whenever my select encouters a timeout, it seems to get stuck there.

I asked a question earlier, so it may seems familiar. As the issue was different, I made a new post. The old post helped me alot to figure out the forking.

Here's my code:

#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);
}

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

◇流星雨 2024-08-20 05:55:32

我能弄清楚!

递归调用 logn 时仍然有问题

,即: ./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);
}

I was able to figure out!

Still buggy when recursivly calling logn

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

Code for ./cmd1

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

Here is my fixed code in case it interests anyone:

#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);
}
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文