Канал - это однонаправленное соединение, которое обычно оказывается между двумя процессами, связанными общим предком, обычно первым из двух создаваемых процессов, если только это не оболочка, в этом случае оболочка создает канал и имеет двадети, которые используют трубу.Канал имеет конец записи, который используется одним процессом;у него есть конец чтения, используемый другим.Часто проще всего организовать подключение стандартного выхода одного процесса к стандартному входу другого.Также проще всего использовать файловые дескрипторы, а не стандартные файловые потоки ввода / вывода.
Последовательность операций:
- Вызов
pipe()
для создания канала. - Вызовите
fork()
для создания дочернего элемента. - Дочерний процесс (возвращаемое значение 0 из
fork()
) выполняет: close()
конец записи канала dup2()
конец чтения канала для стандартного ввода close()
конец чтения канала execve()
дочерний процесс, который будет читать из канала (егостандартный ввод)
- Родительский процесс (возвращаемое значение> 0 из
fork()
) выполняет: close()
конец чтения канала dup2()
конец записи канала в стандартный вывод. close()
конец записи канала execve()
процесс, который будет записывать в канал (его стандартный вывод)
Обратите внимание, что в этом случае вы закрываете оба файловых дескриптора, возвращенных вызовом pipe()
, и закрываете их дважды(один раз в родительском, один раз в дочернем).
Если родительский процесс должен писать дочернему элементу через файловый поток, используйте вызов fdopen()
в дескрипторе файла записи (и не используйте dup2()
на нем или close()
на нем - вы закрываете его с fclose()
в потоке файлов, возвращаемом fdopen()
, или выходом).
Если вы хотите сообщить дочернему процессу, какой файлномер дескриптора, с которого он может прочитать входные данные из канала, тогда вам не нужно делать dup2()
в дочернем элементе;вы можете просто отформатировать строку в массиве символов (во множественном числе - вам нужно как минимум символы и должно быть около дюжины или около того, поскольку это очень дешево), и вы можете затем организовать передачу аргументов в execve()
функция.Помните, что ребенку нужно как минимум три указателя: один для argv [0], название программы;один для номера дескриптора файла;и один для завершающего нулевого указателя.Вот как execve()
знает, когда он достиг конца списка аргументов.Если вы используете execv()
, применяются те же комментарии;вы просто не можете определить среду ребенка (например, список переменных среды, которые он получает);он просто получит ту же среду, которая была у родительского процесса во время fork()
.
Первый шаг в каждом из ¶3 и ¶4 является решающим.Если вы их опустите, труба не будет работать должным образом.