Выполнить приложение. Параметры в поток ввода, результат из потока вывода
От: dosik Россия www.dosik.ru
Дата: 22.07.15 10:58
Оценка:
Добрый день.

Осваиваюсь в *nix (ранее писал только под Windows) системах.
Возникла следующая задача: необходимо выполнить из своей программы внешнюю программу таким образом, чтобы в ее поток ввода передать ей некие значения, а результат ее работы получить из ее потока вывода и отобразить результаты внутри своей программы.
С начала смотрел в сторону exec*, но там немного не то.
Язык — С++.
Заранее благодарен.
Re: Выполнить приложение. Параметры в поток ввода, результат из потока вывода
От: andrey.desman  
Дата: 22.07.15 12:04
Оценка:
Здравствуйте, dosik, Вы писали:

D>Добрый день.


D>Осваиваюсь в *nix (ранее писал только под Windows) системах.

D>Возникла следующая задача: необходимо выполнить из своей программы внешнюю программу таким образом, чтобы в ее поток ввода передать ей некие значения, а результат ее работы получить из ее потока вывода и отобразить результаты внутри своей программы.
D>С начала смотрел в сторону exec*, но там немного не то.
D>Язык — С++.
D>Заранее благодарен.

Для одностороннего общения можно было бы использовать popen. Для двустороннего придется писать самому.
google pipe/fork/dup2/exec

Второй пример здесь:
http://www.cim.mcgill.ca/~franco/OpSys-304-427/lecture-notes/node28.html
Re: Выполнить приложение. Параметры в поток ввода, результат из потока вывода
От: smeeld  
Дата: 22.07.15 12:12
Оценка:
Здравствуйте, dosik, Вы писали:

Погуглите про межпроцессные взаимодействия, каналы, очередя сообщений, шаред память...
Re[2]: Выполнить приложение. Параметры в поток ввода, резуль
От: dosik Россия www.dosik.ru
Дата: 22.07.15 12:12
Оценка:
Здравствуйте, andrey.desman, Вы писали:

AD>Для одностороннего общения можно было бы использовать popen. Для двустороннего придется писать самому.

AD>google pipe/fork/dup2/exec

AD>Второй пример здесь:

AD>http://www.cim.mcgill.ca/~franco/OpSys-304-427/lecture-notes/node28.html

Это именованные каналы. В таком случае мне проще сокетами сделать. Мне же нужно через потоки вводы/вывода. Одну порцию отдать и одну порцию забрать. Что-то типа:
$ cat somefile | ./someexec | ./myapp

Ну очень грубо, просто перенаправить потоки.
Отредактировано 22.07.2015 12:14 dosik . Предыдущая версия .
Re[3]: Выполнить приложение. Параметры в поток ввода, результат из потока вывода
От: andrey.desman  
Дата: 22.07.15 12:13
Оценка:
Здравствуйте, dosik, Вы писали:

D>Это именованные каналы. В таком случае мне проще сокетами сделать. Мне же нужно через потоки вводы/вывода. Одну порцию отдать и одну порцию забрать. Что-то типа:

>> cat somefile | ./someexec | ./myapp
D>Ну очень грубо, просто перенаправить потоки.

Это не именованные каналы, это именно перенаправление потоков. Читай внимательнее.
Re: Выполнить приложение. Параметры в поток ввода, результат
От: vsb Казахстан  
Дата: 22.07.15 12:36
Оценка: 12 (1) +1
Здравствуйте, dosik, Вы писали:

D>Добрый день.


D>Осваиваюсь в *nix (ранее писал только под Windows) системах.

D>Возникла следующая задача: необходимо выполнить из своей программы внешнюю программу таким образом, чтобы в ее поток ввода передать ей некие значения, а результат ее работы получить из ее потока вывода и отобразить результаты внутри своей программы.
D>С начала смотрел в сторону exec*, но там немного не то.
D>Язык — С++.
D>Заранее благодарен.

1. Создаёте два (или три, если нужен stderr) пайпа вызовом pipe().

2. Делаете вызов fork();

3. В дочерней программе делаете dup2(stdinpipe[0], 0), т.е. стандартный ввод заменяете этим пайпом. То же самое делаете со стандартным выводом (1), если нужно — со стандартным выводом ошибок. Закрываете все дескрипторы pipe. Не перепутайте порядок дескрипторов, с stdin ваша программа будет читать, в stdout писать.

4. В дочерней программе делаете exec в нужную вам программу.

5. В родительской программе закрываете те дескрипторы pipe, которые используются дочерней программой.

В принципе всё. В родительской программе пишете в оставшиеся дескрипторы, читаете из них и тд.

Главное вдумчиво почитать man-ы по всем используемым функциям. Ничего сложного, на самом деле.

Раз у вас C++, можете навернуть абстракций над всем этим или какой-нибудь, прости господи, буст заюзать. Там наверное всё это под капотом спрятано. Но вообще это делается вот так.
Отредактировано 22.07.2015 12:37 vsb . Предыдущая версия .
Re: Выполнить приложение. Параметры в поток ввода, результат из потока вывода
От: Кодт Россия  
Дата: 23.07.15 13:44
Оценка:
Здравствуйте, dosik, Вы писали:

D>Возникла следующая задача: необходимо выполнить из своей программы внешнюю программу таким образом, чтобы в ее поток ввода передать ей некие значения, а результат ее работы получить из ее потока вывода и отобразить результаты внутри своей программы.

D>С начала смотрел в сторону exec*, но там немного не то.

popen2 = popen() + fork() + exec()
https://dzone.com/articles/simple-popen2-implementation
Перекуём баги на фичи!
Re[2]: Выполнить приложение. Параметры в поток ввода, результат из потока вывода
От: smeeld  
Дата: 23.07.15 14:38
Оценка:
Здравствуйте, Кодт, Вы писали:

К>popen2 = popen() + fork() + exec()


А shared memory быстрее.
Re[3]: Выполнить приложение. Параметры в поток ввода, результат из потока вывода
От: dosik Россия www.dosik.ru
Дата: 23.07.15 14:55
Оценка:
Здравствуйте, smeeld, Вы писали:

S>А shared memory быстрее.


Быстрее, если это передаю данные в свое приложение, а не в стороннее или в системную утилиту, например gper.
Re[2]: Выполнить приложение. Параметры в поток ввода, результат
От: v_andal Германия  
Дата: 24.07.15 07:05
Оценка:
Здравствуйте, vsb, Вы писали:

vsb>В принципе всё. В родительской программе пишете в оставшиеся дескрипторы, читаете из них и тд.


Если ввод длинный и может привести к раннему выводу, то придётся как-то позаботится о дед-локе. Либо какой-нибудь select запользовать, либо ещё один форк для вкачивания ввода, либо отдельный поток. По вкусу
Re: Выполнить приложение. Параметры в поток ввода, результат из потока вывода
От: dosik Россия www.dosik.ru
Дата: 24.07.15 07:10
Оценка:
Всем огромное спасибо за помощь. Общее направление мне понятно. Дальше буду развивать и думать. popen() + fork() + exec() конечно долговато при условии многоразового одновременного выполнения. Буду думать. Спасибо!
Re: Выполнить приложение. Параметры в поток ввода, результат
От: VTT http://vtt.to
Дата: 24.07.15 07:19
Оценка:
Здравствуйте, dosik, Вы писали:

D>Добрый день.


D>Осваиваюсь в *nix (ранее писал только под Windows) системах.

D>Возникла следующая задача: необходимо выполнить из своей программы внешнюю программу таким образом, чтобы в ее поток ввода передать ей некие значения, а результат ее работы получить из ее потока вывода и отобразить результаты внутри своей программы.
D>С начала смотрел в сторону exec*, но там немного не то.
D>Язык — С++.
D>Заранее благодарен.

Есть готовое решение — libexecstream — позволяет запускать приложения и предоставляет их ввод/вывод в виде стандартных iostream потоков.
Библиотека несколько старовата, но вполне рабочая. И никакого ковыряния в сишном посиксе.
Говорить дальше не было нужды. Как и все космонавты, капитан Нортон не испытывал особого доверия к явлениям, внешне слишком заманчивым.
Отредактировано 24.07.2015 7:22 VTT . Предыдущая версия .
Re[3]: Выполнить приложение. Параметры в поток ввода, результат
От: vsb Казахстан  
Дата: 24.07.15 16:37
Оценка:
Здравствуйте, v_andal, Вы писали:

vsb>>В принципе всё. В родительской программе пишете в оставшиеся дескрипторы, читаете из них и тд.


_>Если ввод длинный и может привести к раннему выводу, то придётся как-то позаботится о дед-локе. Либо какой-нибудь select запользовать, либо ещё один форк для вкачивания ввода, либо отдельный поток. По вкусу


Если нам не интересен вывод дочерней программы, можно его перенаправить в /dev/null. Если интересен — да, надо помнить, что буферы в pipe ограниченного размера.
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.