Прочитайте до закрытия трубы

Я сейчас работаю над домашним заданием для ознакомления с операционными системами, и мне очень весело, но одновременно замешана. Сейчас я работаю над трубопроводом; мой код ниже.

Первоначально мой код выглядел так:

// Child process - write if (fork() == 0) { fprintf(stderr, "Child\r\n"); close(1); dup(p[1]); close(p[0]); close(p[1]); runcmd(pcmd->left); // Parent process - read } else { wait(0); close(0); dup(p[0]); close(p[0]); close(p[1]); fprintf(stderr, "Parent\r\n"); runcmd(pcmd->right); } 

Мой мыслительный процесс по этому поводу состоял в том, что родитель будет ждать, пока ребенок не будет разорван, а затем прочитан из трубы, и это все. Я отправил этот код моему инструктору на нашу страницу обсуждения, и он сказал мне, что с кодом было несколько проблем, один из которых был:

  1. Родительский процесс может бесконечно зависать, если ребенок работает на достаточно длинном входе, который блокирует канал.

Он упомянул, что правильная реализация (в отношении wc ) будет заключаться в использовании команды чтения блокировки, которая будет ждать на трубе до тех пор, пока данные не будут доступны, а затем начните читать, пока труба не будет закрыта.

Я попытался оглянуться, чтобы «прочитать» из трубы в тот момент, когда у него были данные, но не знал, как обойти его. В конце концов, пытаясь решить проблему с возможностью долго ждать на заблокированном канале, у меня родитель и ребенок выполнялись одновременно параллельно, но это может означать, что процесс чтения может завершиться первым и не прочитать в все данные перед записью закончены. Как мне решить проблему?

  int p[2]; pipe(p); // Child process - read if (fork() == 0) { fprintf(stderr, "Start child\r\n"); close(0); dup(p[0]); close(p[0]); close(p[1]); fprintf(stderr, "Child\r\n"); runcmd(pcmd->right); // Parent process - write } else { fprintf(stderr, "Start parent\r\n"); close(1); dup(p[1]); close(p[0]); close(p[1]); fprintf(stderr, "Parent\r\n"); runcmd(pcmd->left); } 

Изменить: я также попробовал команду read , но не знал, как ее использовать, поскольку для этого требуется буфер, а также ожидаемый размер для чтения (?). Я не уверен, как получить любой из них, когда вы не знаете размер входящих данных.

  • Извлечение архива путем компоновки содержимого архива в команду tar
  • Целый конвейерный киоск при промывке USB-накопителя
  • Как я могу выйти из системы меньше, не покидая исходный процесс?
  • Цепочка команд терминала Linux
  • вывести выход parec в sox
  • Что такое переносимый (POSIX) способ достижения замещения процесса?
  • Как «bash» или «gnome-terminal» печатает информацию о пользователе и пути?
  • Вывод трубы из программы, которая выводится только в файл
  • One Solution collect form web for “Прочитайте до закрытия трубы”

    Трубопроводы просты. Вы делаете это тяжело для себя, прыгая в бассейн в глубоком конце. (Или, возможно, это вина вашего инструктора за то, что вы не лучше вас ведете).

    Чтобы стать более комфортно с трубами, я предлагаю вам написать две тривиально простые программы:

    1. Один, который просто пишет текст на стандартный вывод и выходит. Используйте printf , write , fprintf(stdout, …) или любые другие функции, которые вам нравятся.
    2. И тот, который просто читает текст со стандартного ввода и записывает его на стандартный вывод. Используйте getc , getc , read или любые другие функции, которые вам нравятся. Выйдите, когда вы получите конец файла. Проверьте страницу руководства для любой функции, которую вы используете, чтобы увидеть, как она указывает конец файла.

    Не называйте pipe , dup или что-то необычное – даже не open и не close . (Не включайте код отладки и / или аудита, который вы хотите убедиться, что вы понимаете, что происходит, когда.) И затем запустите prog1 | prog2 prog1 | prog2 . Если вы сделали это правильно, вы получите ожидаемый результат.

    Теперь попробуйте «сломать» его, добавив вызовы sleep в программы. Если вы нарушите его, сообщите мне, как вы это сделали. Это должно быть почти невозможно – если вы не сделаете одну программу (или и то и другое) спать дольше, чем вы готовы сидеть и ждать, вы всегда получите prog2 для вывода всех данных, которые prog1 пишет.

    И в случае, если приведенный выше пример не дает понять: правильное выполнение родительского и дочернего (или, в общем, процессов с обеих сторон канала) выполняется одновременно. 1 Программа чтения не будет «завершаться первой» только потому, что в настоящее время нет данных в трубе. Как вы должны были узнать из вышеприведенного упражнения, если программа пытается читать из канала, который в настоящее время не содержит данных, системный вызов read заставляет программу ждать, пока не поступят данные. Программа чтения не будет прервана до тех пор, пока в трубе не останется данных и больше не появится . 2 (На этом этапе read вернет конец файла.) Условие «больше не приносит данных» указывается программой записи, закрывающей трубу (или выходящей, что эквивалентно, поскольку вызовы exit close на всех открытых файловые дескрипторы).

    Я не понимаю, почему вы потёте системный вызов на этом этапе – хотя, если вы еще не знаете, как его использовать, это подтверждает мое подозрение, что ваш инструктор представляет материал из логического порядка. (Я предполагаю, что вы имеете в виду read системный вызов, а не команду read ). Единственный способ, которым ваша программа имеет смысл, – это runcmd(pcmd->right) что читает со стандартного ввода каким-то методом (например, наша программа prog2 , выше ). Похоже, ваша программа просто выполняет функцию оболочки – настраивает каналы, а затем запускает программы. На этом уровне нет никакой причины для вашей программы (в той степени, в которой вы ее нам показали) делать какие-либо ввод-вывод (чтение или запись).
    __________
    1 Связанное чтение: В каком порядке выполняются команды с каналами?
    2 Конечно, это упрощение. Как вы скоро узнаете, если вы еще этого не сделали, вы можете сконструировать программу чтения для завершения, когда в трубе нет данных в настоящее время, но это не поведение по умолчанию. Или вы можете разработать программу чтения для завершения в любом количестве других условий – например, если она считывает q из трубы. Или это может быть убито сигналом и т. Д. …

    Linux и Unix - лучшая ОС в мире.