Должен ли я сделать новый канал для каждой пары процессов в C? - PullRequest
1 голос
/ 24 октября 2011

Если у меня есть 4 процесса, которые я хочу передать:

process1  |  process2  |  process3  |  process4

мне нужно сделать 3 отдельные трубы, как это

int pipe1[2];
int pipe2[2];
int pipe3[2];

или я могу как-то переработать имена каналов, как в этом псевдокоде:

int pipe1[2];             // we use ONLY two pipe names: pipe1
int pipe2[2];             //                         and pipe2

pipe(pipe1);              // getting 2 file descriptors here
pipe(pipe2);              // and 2 here

for process=1 to 4
  if (process==3)         // getting 2 new file descriptors for
     pipe(pipe1);         // process3|process4 (reusing pipe1)

  fork()                  // forking here
  if (child 1) then
    use pipe1
  if (child 2) then
    use pipe1
    use pipe2
  if (child 3) then
    use pipe2
    use pipe1             //the pipe1 that we re-pipe()ed
  if (child 3) then
    use pipe1             //the pipe1 that we re-pipe()ed

Будет ли это работать? Я не уверен, что повторная отправка pipe1 повлияет на предыдущие разветвленные процессы, которые использовали pipe1.

Ответы [ 3 ]

2 голосов
/ 24 октября 2011

Краткий ответ: нет, "repiping" pipe1 не повлияет на предыдущие разветвленные процессы, которые использовали pipe1, но лучше объявить 3 pipe и pipe () перед fork () "ИНГ.

Длинный ответ: Чтобы понять почему, давайте сначала посмотрим, что происходит, когда вы создаете «трубу», а затем, что происходит, когда вы «разворачиваете» процесс.

Когда вы вызываете pipe (), он «создает канал (объект, который допускает однонаправленный поток данных) и выделяет пару файловых дескрипторов. Первый дескриптор подключается к концу чтения канала; второй подключается к концу записи».(Это со страницы man pipe)

Эти файловые дескрипторы сохраняются в массиве int, который вы передали в него.

Когда вы вызываете fork (), «Новый процесс (дочерний процесс)»должна быть точной копией вызывающего процесса "(Это со страницы man fork ())

Другими словами, родительский процесс создаст дочерний процесс, и у этого дочернего процесса будет собственная копия данных.

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

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

Для получения дополнительной информации о fork () и pipe () посмотрите http://beej.us/guide/bgipc/output/html/multipage/index.html

1 голос
/ 24 октября 2011

Вам нужен один канал и, следовательно, один вызов pipe() для каждого | символа в вашей команде.

Вам не нужно использовать три отдельных int [2] массива для хранения дескрипторов файла канала. Система не заботится о том, в какой переменной вы храните дескрипторы файла канала - они просто int s.

1 голос
/ 24 октября 2011

Способ, которым я делал это в прошлом, и способ, которым я бы делал это снова, состоял в том, чтобы не использовать трубы повторно и в итоге получить трубы N-1.Это также зависит от того, хотите ли вы, чтобы одновременно было запущено более двух процессов, взаимодействующих друг с другом, если это так, то у вас, очевидно, возникнут проблемы с повторным использованием двух каналов.

...