Цикл неназванного канала в C - PullRequest
0 голосов
/ 26 апреля 2011

Хорошо, я искал это, но не смог его найти.Приносим свои извинения, если на него уже был дан ответ.

В основном у меня есть программа для класса, которая создает два безымянных канала и использует их для связи между родительским и дочерним процессами.Команда передается от родителя к дочернему элементу, где дочерний элемент выполняет ее и возвращает сообщение об успехе / ошибке родительскому элементу.Затем родитель печатает сообщение об успехе / ошибке.Достаточно просто, у меня это работает.Проблема в том, что мне нужно зациклить его, пока пользователь не выдаст команду «выход».Я думаю, что мне нужен цикл 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 Ответ

4 голосов
/ 26 апреля 2011

Вам нужно создать ребенка до того, как вы войдете в цикл.

Вы также должны быть намного осторожнее с сантехникой.Основной (родительский) процесс должен закрывать концы каналов, которые он не будет использовать, и дочерний процесс (отмечая, что дочерний процесс закрывает противоположные концы от родительского).Конечно, если дочерний элемент читает стандартный ввод и пишет на стандартном выводе, то вы должны организовать дублирование каналов для правильных дескрипторов, а затем дочерний процесс закроет все дескрипторы, возвращаемые вызовом 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");
    }
}
...