почему я не получаю результат stdout от дочернего процесса

У меня две программы: программа Vanilla и программа verB. Мои инструкции заключаются в том, что основной процесс будет иметь дело с вводом-выводом от пользователя, а дочерний процесс вызовет execve() и запустит процесс Vanilla. Для этого мне нужно использовать dup2() для замены stdin\stdout в обоих каналах. (Программа Vanilla должна использовать fgets() для чтения из конвейера). Внутри программы Vanilla я читаю две строки от пользователя до тех пор, пока не будет нажато ctrl+D, Vanilla вызывает xorMethod(), который что-то делает (не имеет значения, что) и возвращает результат.

Когда я запускаю программу verb в Linux(), я получаю только строку «Пожалуйста, вставьте сначала», а затем ничего не происходит, и программа перестает работать. Я хочу, чтобы родитель продолжал получать две строки до тех пор, пока не будет нажато ctrl+D, и выводил на экран результат, который он получил от своего дочернего элемента.

Ваниль.c

#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/wait.h>
#include "Vanila.h"
#include "xor.h"
#define MAXLEN 80
int main()
{
    char s1[MAXLEN + 1];
    char s2[MAXLEN + 1];
    while (!feof(stdin))
    {

        if (readString(s1) == -1)
            break;
        if (readString(s2) == -1)
            break;

        fflush(stdin);
        int res = xorMethod(s1, s2);
        printf("%s xor %s = %d", s1, s2, res);
    }

    return 1;

}

int readString(char * string)
{
    if ((fgets(string, MAXLEN + 1, stdin) < 0 || feof(stdin)))
        return -1;

    string[strcspn(string, "\n")] = 0;
    return 1;

}

верБ.с

#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/wait.h>
#include "Vanila.h"
#define MAXLEN 80
int readStr(char * string);
int main()
{
    int pipeToChild[2];
    int pipeToParent[2];
    char * argv[] = { "./Vanilla",NULL };
    if (pipe(pipeToChild) == -1)
        return -1;
    if (pipe(pipeToParent) == -1)
        return -1;


    pid_t pid = fork();
    if (pid == -1)
        return -1;
    if (pid == 0) //CHILD proccess
    {
        close(pipeToChild[0]);
        close(pipeToParent[1]);
        dup2(pipeToChild[0], fileno(stdin));
        dup2(pipeToParent[1], fileno(stdout));
        execve(argv[0], argv, NULL);
    }
    else
    {
        char string1[MAXLEN + 1];
        char string2[MAXLEN + 1];
        char result[MAXLEN + 1];
        close(pipeToChild[0]);
        close(pipeToParent[1]);
        while (!feof(stdin))
        {
            printf("Please insert first string : ");
            if (readStr(string1) == -1)
                return -1;
            printf("Please insert second string : ");
            if (readStr(string2) == -1)
                return -1;

            write(pipeToChild[1], string1, strlen(string1));
            write(pipeToChild[1], string2, strlen(string2));
            read(pipeToParent[0], &result, MAXLEN);
            printf("%s\n", result);

        }
        wait(NULL);

    }
    return 1;

}

int readStr(char * string)
{
    if ((fgets(string, MAXLEN + 1, stdin) < 0 || feof(stdin)))
        return -1;

    string[strcspn(string, "\n")] = 0;
    return 1;

}



person Karen Moria Reich    schedule 20.05.2021    source источник


Ответы (1)


Вы закрываете неправильные концы каналов в дочернем процессе. Вы закрываете конец чтения pipeToChild, а затем dup2 стандартный поток ввода, поэтому ваша дочерняя программа будет иметь закрытый стандартный поток ввода. Вы должны закрыть конец записи pipeToChild и конец чтения pipeToParent в дочернем процессе и наоборот в основном процессе:

if (pid == 0) //CHILD proccess
{
    close(pipeToChild[1]);
    close(pipeToParent[0]);
/* ... */
else //PARENT
{
    close(pipeToChild[0]);
    close(pipeToParent[1]);
person Emanuel P    schedule 21.05.2021
comment
Эй, спасибо за ваш ответ. - person Karen Moria Reich; 22.05.2021
comment
Я пробовал, но, к сожалению, это зацикливается. - person Karen Moria Reich; 22.05.2021
comment
Если вы запустите его из консоли, никогда не будет конца файла, поэтому feof(stdin) никогда не будет истинным. - person Emanuel P; 22.05.2021
comment
@KarenMoriaReich Это не то, что вы пытаетесь попробовать. Это способ сделать каналы от родительского процесса к дочернему процессу. Вы закрываете конец записи в дочернем процессе и конец чтения в родительском процессе. Независимо от других проблем, вы должны сделать это именно так. - person Emanuel P; 22.05.2021