在 C 中循环无名管道

0 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;
}
}
Run Code Online (Sandbox Code Playgroud)

Jon*_*ler 5

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

您还需要更加小心管道。主(父)进程必须关闭它不会使用的管道末端,子进程也必须关闭(请注意,子进程关闭与父进程相反的末端)。当然,如果子进程正在读取标准输入并在标准输出上写入,那么您必须安排将管道复制到正确的描述符,然后子进程关闭调用返回的所有描述符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");
    }
}
Run Code Online (Sandbox Code Playgroud)