Как я могу записать строки в файл, используя родительский и два дочерних процесса? - PullRequest
0 голосов
/ 15 мая 2018

Я пытаюсь решить эту проблему, но не могу.

Вот краткое описание:

У нас есть родитель с двумя дочерними процессами (child_a, child_b) и N строками.

Текущие данные: данные [i] (0 ... N)

  1. Родитель запускается и ждет сигнала от child_b. Child_a ждет.
  2. Child_b отправляет сигнал родителю и ожидает данные.
  3. Родитель записывает данные [i] в ​​канал и ожидает
  4. Child_b читает данные [i] из pipe и printf (). Тогда ждем Child_a
  5. Child_a генерирует случайное число (от 1 до 5) и записывает в трубу.
  6. Child_b читает rand из pipe и отправляет его родителю.
  7. Родитель записывает «data [i] - rand» в файл.
  8. И начнем с начала со следующих данных ...

Вот мой код:

FILE *fp2;
fp2 = fopen("bill.dat" , "a");

pid_t child_a, child_b;
int pipefd_a[2], pipefd_b[2];
char msg[100];
char sleep_time[10];

int stat;

signal(SIGUSR1, handler);
signal(SIGUSR2, handler);

if(pipe(pipefd_a) == -1 || pipe(pipefd_b) == -1){
    perror("Error\n");
    exit(EXIT_FAILURE);
}

int i;
for(i = 0; i < n; i++){

    child_a = fork();

    if(child_a < 0){
        perror("Error\n");
    }

    if(child_a == 0){
        sleep(1);
        printf("Child_a-----\n");
        srand(time(NULL));
        int r = rand()%5+1;
        char rand[2];
        sprintf(rand, "%d", r);
        printf("Child_a rand: %s\n", rand);
        write(pipefd_b[1], rand, strlen(rand)+1);
        printf("Child_a end-----\n");
        exit(0);
    }
    else{
        child_b = fork();

        if(child_b == 0){
            printf("Child_b sends a signal to parent\n");
            kill(getppid(), SIGUSR1);
            close(pipefd_a[1]);
            read(pipefd_a[0], msg, sizeof(msg));
            close(pipefd_a[0]);
            printf("Child_b reads from pipe (from parent): %s\n", msg);
            kill(child_a, SIGUSR2);
            sleep(2);
            read(pipefd_b[0], sleep_time, 10);
            printf("Child_b reads from pipe (from child_a): %s\n", sleep_time);
            fflush(NULL);
            write(pipefd_b[1], sleep_time, sizeof(sleep_time));
            close(pipefd_b[1]);
            printf("Child_b end-----\n");
            exit(0);

        }
        printf("============== %d ============== \n", i);
        printf("Parent waiting for signal...\n");
        pause();
        printf("Signal received\n");
        printf("Parent write into pipe\n");
        close(pipefd_a[0]);
        write(pipefd_a[1], data[i].address, 100);
        kill(child_b, SIGUSR2);
        waitpid(child_b, &stat, 0);
        read(pipefd_b[0], msg, sizeof(msg));
        fprintf(fp2, "%s - %s\n", data[i].address, msg);
        printf("Parent writes into file: %s\n", msg);
    }

}
fclose(fp2);

и мой вывод (n = 2):

  • data1 - 1
  • data1 - 1
  • data1 - 1
  • data2 - 3

В файле всегда есть 2 ^ n строк. Для этого требуется два дочерних процесса, и я подозреваю, что проблема связана с «fork ()» внутри цикла, но я не понимаю, что я делаю неправильно.

1 Ответ

0 голосов
/ 15 мая 2018

Первая проблема заключается в том, что вы запускаете процесс создания цикла for.Вот почему вы получаете 2n строк.Если вы хотите прочитать какой-либо файл формы данных N раз, вы не выполняете N процессов.

Во-вторых, вам нужно 3 канала для работы.Канал является однонаправленным, то есть один процесс может писать только в канал, а другой - только читать из него.Один конец предназначен для записи, а другой - для чтения, поэтому вы должны закрыть неиспользуемые дескрипторы!

  • Первый канал используется, когда родительский элемент записывает данные [i] в ​​канал, а child_b читает
  • второй канал используется, когда child_a записывает случайное число в канал, а child_b читает
  • третий канал используется, когда child_b записывает в канал, а родитель выполняет чтение

Если вы можете записать целоеПрограмму мне было бы легче понять и помочь вам.Это скелет, как я бы попытался сделать эту работу

int pipe_parent_to_childB[2], pipe_childB_to_parent[2], pipe_childA_to_childB;

if(pipe(pipe_parent_to_childB) == -1 || pipe(pipe_childB_to_parent) == -1 ||pipe(pipe_childA_to_childB) == -1)
{
            perror("Error\n");
            exit(EXIT_FAILURE);
}

//close read end because parent will write to pipe
close(pipe_parent_to_childB[0]);

switch(fork()) //create child b
{
    case -1:
        //error
    case 0:
        //now you are in child_b
        close(pipe_parent_to_childB[1]);
        close(pipe_childA_to_childB[1]);

        //perform some action


    default:
        break;
        }
}
switch(fork()) //crete child a
{
     case -1:
                //error
     case 0:
                //now you are in child_a
                close(pipe_childA_to_childB[0]);
                //perform some action

     default:
         break;


}

//here you are in parent process again. Send signals, wait for signals and write to pipe here
//from parent you send some data through pipe to process child_b N times
//after this you close write end of the pipe descriptor.
...