Используйте механизм IPC pipe для завершения программы, чтобы дочерний и родительский элементы выводили одинаковые выходные данные. - PullRequest
0 голосов
/ 22 марта 2019

Итак, недавно у меня был экзамен в классе по операционным системам, и он попросил меня написать программу с использованием pipe ().Эта программа была предназначена для отправки и получения данных через канал, чтобы независимо от того, какой файл был запущен, выходные данные были одинаковыми.

Вывод должен быть следующим:

Hello (от дочернего элемента) 1

Hello (от родительского элемента)

Hello (от дочернего элемента)2

Код шаблона был задан следующим образом.(Я не мог изменить этот код, я только вставил код, чтобы он работал).Нет творчества ... Я знаю.

#include <unistd.h>
#include <stdio.h>
#include <sys/stat.h>
#include <sys/wait.h>
#include <signal.h>

int main() {
    pid_t pid;
    char buf[32];



    if ((pid = fork()) < 0) {
        puts("Error");
    } else if(pid == 0) { //child


        fprintf(stdout, "Hello (from child) 1\n");



        fprintf(stdout, "Hello (from child) 2\n");

        fflush(stdout);

    }
    else {


        fprintf(stdout, "Hello (from parent)\n");


    }
}

Через некоторое время мой вывод был следующий.Но после выполнения ничего не печатается.(Я не мог проверить это, потому что это был бумажный экзамен, но я проверял это позже).Кроме того, я был в затруднительном положении, так что я знаю, что ошибки, вероятно, часты.

Я добавил User Start и User End, чтобы показать, где я мог изменить код.Буду признателен за любую помощь.

#include <unistd.h>
#include <stdio.h>
#include <sys/stat.h>
#include <sys/wait.h>
#include <signal.h>

int main() {
    pid_t pid;
    char buf[32];

    // User Start
    int fds[2];
    pipe(fds);
    close(1);
    dup(fds[1]);
    // User End

    if ((pid = fork()) < 0) {
        puts("Error");
    } else if(pid == 0) { //child

        // User Start

        // User End
        fprintf(stdout, "Hello (from child) 1\n");

        // User Start
        write(fds[1],"Hello (from child) 1\n",21);
        read(fds[0],buf,21);
        write(fds[1],"Hello (from child) 2\n",21);
        // User End

        fprintf(stdout, "Hello (from child) 2\n");
        // User Start

        // User End

    }
    else {
        // User Start
        read(fds[0],buf,21);
        // User End

        fprintf(stdout, "Hello (from parent)\n");
        // User Start
        write(fds[1],"Hello (from parent)\n",21);
        read(fds[0],buf,21);

        // User End

    }
}

ОБНОВЛЕНИЕ

#include <pthread.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <stdint.h>


int main()
{
    pid_t pid;
    char buf[32];
    int returnstatus1;
    int fds[2];

    returnstatus1 = pipe(fds);
    printf("Return status = %d\n",returnstatus1);  //check if pipe is created or not

    if(returnstatus1 == -1)
  {
    printf("Pipe 1 could not be created\n");
    return 1;
  }

    if((pid = fork()) < 0)
    {
        puts("ERROR");
    }
    //child
    else if(pid == 0)
    {

        fprintf(stdout,"hello (from child) 1\n");
        close(fds[0]);
        write(fds[1],"hello  (from child) 1\n",21);
        close(fds[1]);
        read(fds[0],buf,21);
        fprintf(stdout,"hello (from child) 2\n");
        close(fds[0]);
        write(fds[1],"hello  (from child) 2",21);
    }
    //parent
    else
    {
        close(fds[1]);
        read(fds[0],buf,21);
        fprintf(stdout,"hello (from parent)\n");
        close(fds[0]);
        write(fds[1],"hello (from parent)\n",21);
        close(fds[1]);
        read(fds[0],buf,21);
    }

    return 0;
}

1 Ответ

1 голос
/ 22 марта 2019

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

Так как это понятнее, я сначала покажу родителя, а не ребенка. Конечно, не имеет значения, в каком порядке вы разместите ветки if - вы можете адаптировать их к формату экзамена, и я настоятельно рекомендую вам сделать это, чтобы освоить его.

Имея это в виду, мы идем вперед:

#include <stdio.h>
#include <unistd.h>

int main (void) {
  pid_t pid;
  char buf;
  int parent_pipes[2];
  int child_pipes[2];
  pipe(child_pipes);
  pipe(parent_pipes);
  if ((pid = fork()) < 0)
      puts("Error");
  else if (pid) {
    // parent first!
    // wait for the child to write something into the pipe...
    read(*child_pipes, &buf, 1);
    // and now write to stdout, and tell the child that we're ready
    fprintf(stdout, "Hello (from parent)\n");
    fflush(stdout);
    write(parent_pipes[1], "R", 1); // it doesn't matter what we write; we have to write anything
  } else {
    // and now the child
    // output and flush...
    fprintf(stdout, "Hello (from child) 1\n");
    fflush(stdout);
    // ...and tell the parent that we're ready
    write(child_pipes[1], "R", 1); // write end of the pipe
    // now wait!
    read(*parent_pipes, &buf, 1); // read end of the pipe
    fprintf(stdout, "Hello (from child) 2\n");
  }
  return 0;
}
...