У меня есть библиотека, который имеет довольно приятную легкую абстракцию ввода-вывода для таких вещей, как TCP-соединения или socketpair, и я пытаюсь использовать его для связи с подпроцессом через stdin и stdout.
Однако библиотека ввода-вывода предполагает возможность чтения и записи из одного и того же файлового дескриптора, тогда как у меня один для чтения и один для записи соответственно. Теперь мне было интересно, есть ли у меня простой способ объединить два файловых дескриптора таким образом, чтобы он выглядел как один fd, но в фоновом режиме он просто мультиплексирует чтение в stdout и запись в stdin подпроцесса.
Возможно ли это вообще, и насколько при этом задействована черная магия? Не лучше ли оставить два отдельных полуоткрытых соединения?
Я надеялся, что есть что-то вроде dup2, которое позволит мне дублировать записывающую сторону stdin на stdout, но я не могу найти ничего на этот счет.
Никогда не слышал о чем-либо подобном - вызов функции, который позволяет вам рассматривать один файловый дескриптор как чтение одного (другого) файлового дескриптора, а также запись в один (другой) файловый дескриптор. Конечно, есть файловые дескрипторы чтения-записи, но, насколько я понимаю, они не имеют отношения к вашему контексту.
Однако файловые дескрипторы чтения-записи могут быть одним из способов решения вашей проблемы; OTOH, позиционирование файлов может оказаться неразрешимым. Розетки и трубы не доступны; это меняет проблемы с положением файла. Более серьезно, если вы пишете в сокет, только другой конец может его прочитать. Если вы пишете на конце канала для записи, ничто не может помешать записывающему устройству прочитать данные с конца канала для чтения. Если вы пишете в файл, любой процесс может читать то, что было написано, но вы переместили позицию файла в файловый дескриптор чтения-записи.
Разве вы не можете создать пару сокетов, затем fork() для создания подпроцесса, а затем в дочернем dup2() дескриптор одного конца пары сокетов для дочерних fd 0 и fd 1 (это два отдельных вызова dup2())? После этого вы можете close () этот дескриптор пары сокетов, вы больше не будете его использовать. Тогда ваша библиотека ввода-вывода в родительском элементе сможет читать и записывать дескриптор для другого конца пары сокетов.
Это то, чего я хотел избежать, поскольку для этого потребовалось бы необычное использование stdin (или stdout) в дочернем процессе, в то время как я пытаюсь сохранить дочерний процесс как можно ближе к обычному инструменту cli (т. Е. Разрешить взаимодействия также из оболочки).
@cdecker Вы должны выполнить манипуляции с dup2() в разветвленном дочернем процессе до того, как он вызовет exec() для запуска программы инструмента. Инструмент не знал бы об этих махинациях. Он просто читал бы из stdin и записывал в stdout обычным способом, точно так же, как если бы он был вызван из оболочки.





Вероятно, вам придется серьезно переосмыслить свою легкую абстракцию ввода-вывода. В настоящее время он основан на том, что «один файловый дескриптор может выполнять ввод и вывод», но его необходимо изменить для обработки «для ввода требуется один файловый дескриптор, а для вывода - возможно, другой файловый дескриптор». Ваш код будет направлять операции вывода на дескриптор вывода, операции ввода - на дескриптор ввода. Вы, вероятно, будете использовать свой собственный «дескриптор файла» (который вполне может быть небольшим целым числом, как дескриптор файла - это небольшое целое число), но ваш дескриптор файла не будет (обязательно) совпадать с каким-либо дескриптором файла.