Связка двух дочерних процессов пайпами
От: GuessWho  
Дата: 28.08.10 06:35
Оценка:
Здравствуйте. Столкнулся со следующей проблемой.

Существует родительский процесс выполнения программы по бэкапу информации на флешку. Он должен создавать два дочерних процесса по архивирования и шифрованию данных, отобранных в других модулях программы, не создавая промежуточных файлов. Т.е. желаемая схема: родитель пишет через пайп на stdin gzip'а, stdout gzip'а связан пайпом с stdin'ом OpenSSL'а, который уже пишет в конечный файл.

Модуль, создающий дочерний процесс с перенаправлением stdin и stdout
pid_t exec_redirect(const char *path, char *const args[], int& wr_fd, int rd_fd)
{
    int in[2] = {0};
    // для возможности передачи модулю готового пайпа
    if (wr_fd == 0)
    {
        pipe(in);
    }

    const pid_t child = fork();
    if (child == 0)
    {
        // потомок читает со входа и пишет на выход
        close(in[1]);

        // для возможности передачи уже готового пайпа
        if (wr_fd == 0)
        {
            dup2(in[0], STDIN_FILENO);
        }
        else
        {
            dup2(wr_fd, STDIN_FILENO);
        }
        
        dup2(rd_fd, STDOUT_FILENO);
        execv(path, args);
        perror("execv");
        exit(0);
    }
    else
    {
        // в родителе закрываем чтобы не терять ф.деск.
        close(in[0]);
    }

    if (wr_fd == 0)
    {
    // родитель должен записать данные на вход
    // т.е. у родителя должен быть in[1]
        wr_fd = in[1]; // вход на запись в родителе
    }
    return child;
}


Модуль, вызывающий и связывающий эти два процесса.

FILE* redirect(char* out_fname)
{
    int arch_enc[2] = {0};
    pipe(arch_enc);

    int out = open(out_fname, O_WRONLY | O_APPEND);
    int in = 0;
  
    puts("IO redirect started");

    const char *cmd = "/bin/gzip";
    char *const args[] = {"/bin/gzip", "gzip", "-f", "-", NULL};
    exec_redirect(cmd, args, in, arch_enc[1]);

    const char *cmd2 = "/usr/bin/openssl";
    char *const args2[] = {"/usr/bin/openssl" ,"enc", "-blowfish", "-pass", ENC_PASS, NULL};
    exec_redirect(cmd2, args2, arch_enc[0], out);

    FILE* stream = fdopen(in, "w");
    if (stream == NULL)
    {
        perror("fdopen");
        return NULL;
    }
    return stream;
}


В результате выполнения такого кода оба процесса создаются, но данных на выходе нет, и процессы висят, пока им не сделать kill. Стало интересно, где я ошибся. Под отладчиком видно, что номера ф.д. не портятся, т.е. ошибка где-то в логике. Буду очень рад и благодарен, если кто-нибудь подскажет.
pipe fork child parent redirect stdin stdout
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.