c - 迷失在多个 Fork()、Pipe() 和 Select() 中

标签 c select fork pipe

希望我能在这里找到一些帮助,因为我开始放弃。请注意,这是一项家庭作业,因此它可能很愚蠢。

上下文: 必须编写一些将由 shell 执行的东西,如下所示:
logn [--tick n] cmd [args] [, cmd [args]]...

基本上,它是一个同时运行多个程序的程序。

限制: 每个输出行必须以它的命令号开头,格式为 printf "%d: %s" IE: 0:第一个命令的第一行。
0:第一个命令的第二行。
1:第二个命令的第一行。
0:第一个命令的第三行。
1:第二条命令的第二行。

如果指定了刻度,如果 n 秒内没有发送任何输出,系统将打印一个句点。
必须使用Select()
如果最后输出是句点,系统不会再打印句点。

现在这是我的问题!我可以用一个命令让它工作。当我尝试使其成为多个命令时,我似乎失败了。我相信这可能是我的方法。也许你们中的一些人能够帮助我。

这是我尝试使用多个 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);

}

最佳答案

您需要在一个循环中 fork 所有子级,然后在第二个循环中,从所有子级中读取所有数据。

您想要并行监听所有子级的输出(这就是 select 为您做的事情),但所有子级都需要运行才能工作。您当前的 for 循环生成一个子循环,然后转到 select... 这不是它的正确位置。

关于c - 迷失在多个 Fork()、Pipe() 和 Select() 中,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/1851020/

相关文章:

c - 函数指针 WINAPI

c - 在 for 循环中有效地打印每 x 次迭代

php - MySQL Join 其中匹配的列包含不同的值

c++ - 为什么我会收到 Missing sentinel 警告?

c - 获取指向窗口像素的指针

c - 将整数值输入到 C 中的数组中

c - STDIN 和传入套接字上的 select()

sql - 如何通过 select 和 subselect 或 join 语句获取数据

C: Exec/fork > 失效进程

python - 如何在 C 程序中运行 Python 可执行文件(.py)(例如使用 execvp)?