在C中循环一个未命名的管道

时间:2011-04-26 04:17:50

标签: c loops pipe

好的,我搜索过这个,但找不到它。如果之前已经回答过,请道歉。

基本上我有一个类的程序,它创建两个未命名的管道并使用它们在父进程和子进程之间进行通信。该命令从父级传递给子级,子级执行该命令并向父级返回“成功/错误”消息。然后父输出成功/错误消息。很容易,我有这个工作。问题是现在我需要循环它直到用户给出“退出”命令。我想我需要一个while循环,但在尝试放置后,程序仍然只运行一次然后退出。这就是我所拥有的。希望这是有道理的,我遗漏了代码的处理部分,因为那部分可行(就像我说的,对于一个类)但如果有什么没有意义我会澄清。提前感谢您的帮助。

while (strcmp(cmd,"exit") != 0)
{
/* Create Pipe P to pass command from the  
parent process to the child process and check for errors.*/
    pipe(p);

    /*Create Pipe Q to pass command from the
child process to the parent process and check for errors. */
pipe(q);

/* Create child process */
pid = fork();

switch(pid){

    case -1: /* fork failed */
        perror("main: fork");
        exit(1);
    case 0: /* Child process */
        /*****************************************
                    Stuff being executed in the child process
                    *****************************************/
    default: /* Parent process */
         printf ("Choose from the following list of commands.\n");
            printf ("display\n");
            printf ("chars\n");
            printf ("lines\n");
            printf ("words\n");
            printf ("find\n");
            printf ("exit\n");
            fgets (cmd,10,stdin);

        if ((c = strchr(cmd, '\n')) != NULL)
            {
             *c = '\0';
            }
        /**********************************
                    Pipes being opened and closed for
                    communication between parent and child
                    **************************************/
                break;
    }
    return 0;
}
}

1 个答案:

答案 0 :(得分:4)

您需要在进入循环之前创建孩子。

您还需要对管道更加小心。主(父)进程必须关闭它不会使用的管道的末端,同样关闭子进程(注意到子进程与父进程相反)。当然,如果孩子正在阅读标准输入并在标准输出上书写,那么你必须安排将管道复制到正确的描述符,然后孩子关闭pipe()调用返回的所有描述符。


尝试使用此尺寸 - 您必须展开be_childish()才能完成实际工作......

#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <stdarg.h>
#include <string.h>
#include <errno.h>

static void be_childish(int p[2], int q[2]);
static void be_parental(int p[2], int q[2]);

static void err_exit(const char *fmt, ...)
{
    int errnum = errno;
    va_list args;
    va_start(args, fmt);
    vfprintf(stderr, fmt, args);
    va_end(args);
    fprintf(stderr, "\n%d: %s\n", errnum, strerror(errnum));
    exit(1);
}

int main(void)
{
    int   p[2];     /* Pipe to child */
    int   q[2];     /* Pipe to parent */
    pid_t pid;

    if (pipe(p) != 0)
        err_exit("Failed to create pipe 1");

    if (pipe(q) != 0)
        err_exit("Failed to create pipe 2");

    if ((pid = fork()) < 0)
        err_exit("Failed to create child process");
    else if (pid == 0)
        be_childish(p, q);
    else
        be_parental(p, q);

    return(0);
}

static int prompt(char *buffer, size_t buflen)
{
    char *c;
    printf("Choose from the following list of commands.\n");
    printf("display\n");
    printf("chars\n");
    printf("lines\n");
    printf("words\n");
    printf("find\n");
    printf("exit\n");
    if (fgets(buffer, buflen, stdin) == 0)
        return EOF;
    if ((c = strchr(buffer, '\n')) != NULL)
        *c = '\0';
    if (strcmp(buffer, "exit") == 0)
        return EOF;
    return 0;
}

static void be_parental(int p[2], int q[2])
{
    char  cmd[10] = "";

    if (close(p[0]) != 0 || close(q[1]) != 0)
        err_exit("Parent: failed to close pipe");

    while (prompt(cmd, sizeof(cmd)) != EOF)
    {
        char    buffer[4096];
        ssize_t nbytes;
        if (write(p[1], cmd, strlen(cmd)) != (ssize_t)strlen(cmd))
            err_exit("Write to child failed");
        if ((nbytes = read(q[0], buffer, sizeof(buffer))) < 0)
            err_exit("Read from child failed");
        if (nbytes == 0)
            return;
        printf("%s\n", buffer);
    }
}

static void be_childish(int p[2], int q[2])
{
    char    cmd[10] = "";
    ssize_t nbytes;

    if (close(p[1]) != 0 || close(q[0]) != 0)
        err_exit("Child: failed to close pipe");

    while ((nbytes = read(p[0], cmd, sizeof(cmd))) > 0)
    {
        char    buffer[4096];
        cmd[nbytes] = '\0';
        /* Process command */
        strcpy(buffer, "Response from child: ");
        strcat(buffer, cmd);
        if (write(q[1], buffer, strlen(buffer)) != (ssize_t)strlen(buffer))
            err_exit("Write to parent failed");
    }
}