URL: https://www.opennet.me/cgi-bin/openforum/vsluhboard.cgi
Форум: vsluhforumID9
Нить номер: 3129
[ Назад ]

Исходное сообщение
"pipe() + ifstream()"

Отправлено stalker , 05-Июл-04 15:57 
Народ!
Подскажите как правильно сделать такое:

8<-------
int p[4];
pipe(&p[0]); // в трубу писать
pipe(&p[2]); // из трубы читать

pid = fork();
if(!pid) {
    dup2(p[0],0);
    dup2(p[3],1);
    close(лишние дескрипторы);
    execlp("cat", "cat", 0);
}

ofstream foo(p[1]);
foo << (string)data;
foo.close();

// до сих пор все работает.
// и вот тут хочется что-то типа

ifstream bar(p[2]);
bar >> data;

// как правильно инициализировать поток, чтобы он за раз все данные отдал?

waitpid(pid, .... );

8<---------

ЗС,
Стас



Содержание

Сообщения в этом обсуждении
"pipe() + ifstream()"
Отправлено SergeiZz , 05-Июл-04 16:41 
>int p[4];
>pipe(&p[0]); // в трубу писать
>pipe(&p[2]); // из трубы читать
>
>pid = fork();
>if(!pid) {
>    dup2(p[0],0);
>    dup2(p[3],1);
Последние две строки зачем?

>    close(лишние дескрипторы);
>    execlp("cat", "cat", 0);
>}
>
>ofstream foo(p[1]);
>foo << (string)data;
>foo.close();
>
>// до сих пор все работает.
>// и вот тут хочется что-то типа
Это работает?
У ofstream (как и у ifstream) нет конструктора с аргументом int!

>как правильно инициализировать поток, чтобы он за раз все данные отдал?
Наверно, нужно использовать именованные каналы (fifo)...


"pipe() + ifstream()"
Отправлено stalker , 05-Июл-04 16:59 
>>int p[4];
>>pipe(&p[0]); // в трубу писать
>>pipe(&p[2]); // из трубы читать
>>
>>pid = fork();
>>if(!pid) {
>>    dup2(p[0],0);
>>    dup2(p[3],1);
>Последние две строки зачем?
>
>>    close(лишние дескрипторы);

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

>>    execlp("cat", "cat", 0);

Конечно, это чушь! :))) реально здесь будет "pnmtopng", при чем, всего будет несколько процессов, завязанных каналами (не хочется "приземлять" данные на файловую систему), а-ля "$ cat data | jpegtopnm | pnmtopng"

>>}
>>
>>ofstream foo(p[1]);
>>foo << (string)data;
>>foo.close();
>>
>>// до сих пор все работает.
>>// и вот тут хочется что-то типа
>Это работает?

Работает, да еще как!!!!

>У ofstream (как и у ifstream) нет конструктора с аргументом int!

Выходит, что есть.... я не лазал в ..stream.h, но, видимо "там" знают про инт... по крайней мере ofstream отрабатывает как надо.

>
>>как правильно инициализировать поток, чтобы он за раз все данные отдал?
>Наверно, нужно использовать именованные каналы (fifo)...

Но ведь на выход все работает! Должно и на вход срабатывать....
Скажу больше, из bar удается считать только 4 байта....


"pipe() + ifstream()"
Отправлено SergeiZz , 05-Июл-04 17:12 
>если не закрыть, то дочерний процесс может подвиснуть в piperd, ожидая, что
>в один из открытых каналов я буду что-то писать/читать из парент
>процесса, порождая тем самым дедлок на waitpide. По крайней мере, я
>так это понял, потестировав код, не закрывая каналы с одной и
>с другой стороны. Да... теории не хватает....
Это проще можно... Он и должен так себя вести.

>>>    execlp("cat", "cat", 0);
>
>Конечно, это чушь! :))) реально здесь будет "pnmtopng", при чем, всего будет
>несколько процессов, завязанных каналами (не хочется "приземлять" данные на файловую систему),
>а-ля "$ cat data | jpegtopnm | pnmtopng"
fifo имеет только имя в файловой системе, сам он в ядре. Здесь поэтому
без проблем. Если производительность супер важна (что, судя по Вашим
словам, вряд ли), то надо использовать разделяемую память. При записи в
канал данные копируются в ядро и обратно.

>>>ofstream foo(p[1]);
>>>foo << (string)data;
>>>foo.close();
>>>
>>>// до сих пор все работает.
>>>// и вот тут хочется что-то типа
>>Это работает?
>
>Работает, да еще как!!!!
>
>>У ofstream (как и у ifstream) нет конструктора с аргументом int!
>
>Выходит, что есть.... я не лазал в ..stream.h, но, видимо "там" знают
>про инт... по крайней мере ofstream отрабатывает как надо.
Я лазил! Это истика какая-то. Какой компилятор?

>Но ведь на выход все работает! Должно и на вход срабатывать....
Но ведь и придерживаться стандарта то же нужно :)


"pipe() + ifstream()"
Отправлено stalker , 05-Июл-04 17:24 
>>если не закрыть, то дочерний процесс может подвиснуть в piperd, ожидая, что
>>в один из открытых каналов я буду что-то писать/читать из парент
>>процесса, порождая тем самым дедлок на waitpide. По крайней мере, я
>>так это понял, потестировав код, не закрывая каналы с одной и
>>с другой стороны. Да... теории не хватает....
>Это проще можно... Он и должен так себя вести.

А как проще?

еще знаю fcntl( ... ,FD_CLOEXEC) но какая разница где и как его глушить?

>
>>>>    execlp("cat", "cat", 0);
>>
>>Конечно, это чушь! :))) реально здесь будет "pnmtopng", при чем, всего будет
>>несколько процессов, завязанных каналами (не хочется "приземлять" данные на файловую систему),
>>а-ля "$ cat data | jpegtopnm | pnmtopng"
>fifo имеет только имя в файловой системе, сам он в ядре. Здесь
>поэтому
>без проблем. Если производительность супер важна (что, судя по Вашим
>словам, вряд ли), то надо использовать разделяемую память. При записи в
>канал данные копируются в ядро и обратно.

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

>
>>>>ofstream foo(p[1]);
>>>>foo << (string)data;
>>>>foo.close();
>>>>
>>>>// до сих пор все работает.
>>>>// и вот тут хочется что-то типа
>>>Это работает?
>>
>>Работает, да еще как!!!!
>>
>>>У ofstream (как и у ifstream) нет конструктора с аргументом int!
>>
>>Выходит, что есть.... я не лазал в ..stream.h, но, видимо "там" знают
>>про инт... по крайней мере ofstream отрабатывает как надо.
>Я лазил! Это истика какая-то. Какой компилятор?

$g++ -v
Using builtin specs.
gcc version 2.95.4 200220320 [FreeBSD]
$
от себя: FreeBSD 4.7

>
>>Но ведь на выход все работает! Должно и на вход срабатывать....
>Но ведь и придерживаться стандарта то же нужно :)

согласен. Хотя портинг этому проекту врядтли грозит. ;)


"pipe() + ifstream()"
Отправлено SergeiZz , 08-Июл-04 13:03 
>>>если не закрыть, то дочерний процесс может подвиснуть в piperd, ожидая, что
>>>в один из открытых каналов я буду что-то писать/читать из парент
>>>процесса, порождая тем самым дедлок на waitpide. По крайней мере, я
>>>так это понял, потестировав код, не закрывая каналы с одной и
>>>с другой стороны. Да... теории не хватает....
>>Это проще можно... Он и должен так себя вести.
>
>А как проще?
Тут надо покопаться в формулировке задачки. Если не нужно блокировать
при чтении, но нужно использовать неблокируемое чтение, только и всего.

>производительность не на последнем месте, но мне не хочется изучать кучу графических
>стандартов, чтобы их меж собой тасовать....
>Тем не менее, если есть опыть, пожалуйста поделитесь.
Да там просто всё, например, в Sys V -- shmget() и еже с ним.

>$g++ -v
>Using builtin specs.
>gcc version 2.95.4 200220320 [FreeBSD]
>$
>от себя: FreeBSD 4.7
Ну, про этот реликт надо уточнять, но всё равно -- мистика.

>>>Но ведь на выход все работает! Должно и на вход срабатывать....
>>Но ведь и придерживаться стандарта то же нужно :)
>
>согласен. Хотя портинг этому проекту врядтли грозит. ;)
Даже на gcc-2.96 (для которого точно нет такого конструктора)?


"pipe() + ifstream()"
Отправлено stalker , 08-Июл-04 13:44 
>>>>если не закрыть, то дочерний процесс может подвиснуть в piperd, ожидая, что
>>>>в один из открытых каналов я буду что-то писать/читать из парент
>>>>процесса, порождая тем самым дедлок на waitpide. По крайней мере, я
>>>>так это понял, потестировав код, не закрывая каналы с одной и
>>>>с другой стороны. Да... теории не хватает....
>>>Это проще можно... Он и должен так себя вести.
>>
>>А как проще?
>Тут надо покопаться в формулировке задачки. Если не нужно блокировать
>при чтении, но нужно использовать неблокируемое чтение, только и всего.
>
>>производительность не на последнем месте, но мне не хочется изучать кучу графических
>>стандартов, чтобы их меж собой тасовать....
>>Тем не менее, если есть опыть, пожалуйста поделитесь.
>Да там просто всё, например, в Sys V -- shmget() и еже
>с ним.

а как объяснить внешним утилитам объяснить, что нужно использовать не потоки, а шарную память? Боюсь, не подойдет. fork, pipe и т.п. в данном случае вызваны отсутствием времени на изучение пачки графических стандартов. Если бы знал, полагаю, стринга мне хватило бы.

>
>>$g++ -v
>>Using builtin specs.
>>gcc version 2.95.4 200220320 [FreeBSD]
>>$
>>от себя: FreeBSD 4.7
>Ну, про этот реликт надо уточнять, но всё равно -- мистика.
>
>>>>Но ведь на выход все работает! Должно и на вход срабатывать....
>>>Но ведь и придерживаться стандарта то же нужно :)
>>
>>согласен. Хотя портинг этому проекту врядтли грозит. ;)
>Даже на gcc-2.96 (для которого точно нет такого конструктора)?

не смогу ответить быстро, - у меня его нет. Если хочешь, могу дать исходник для теста.

Кстати, в каком именно ..stream.h искать конструкторы?


"pipe() + ifstream()"
Отправлено SergeiZz , 16-Июл-04 18:29 
>а как объяснить внешним утилитам объяснить, что нужно использовать не потоки, а
>шарную память? Боюсь, не подойдет. fork, pipe и т.п. в данном
>случае вызваны отсутствием времени на изучение пачки графических стандартов. Если бы
>знал, полагаю, стринга мне хватило бы.
Эх... надо подумать... Так... задача такая: надо вывод cat отправить в
разделяемую память, из которой его прочитать своей программой...
Надо подумать...
Но толку тут мало, потому что cat будет использовать каналы всё равно.
Нужна объектно-ориентированная ОС для подобных задач.

>не смогу ответить быстро, - у меня его нет. Если хочешь, могу
>дать исходник для теста.
Брось на zbl@gmail.ru, но только с бесплатного ящика какого нибудь.
Я на этот адрес спам собираю (для научной работы по прагматическому
анализу), а со спамом вирусы в изобилии приходят, и этот адрес широко
известен среди зараженных машин по всему Миру, так что с него посыпаться
вирусы (для Windoze, естессестно) могут запрасто.

>Кстати, в каком именно ..stream.h искать конструкторы?
А я нашёл, в чём дело. И конструктор нашёл. Но сей час времени нет
рассказать...


"pipe() + ifstream()"
Отправлено stalker , 16-Июл-04 18:49 
>>а как объяснить внешним утилитам объяснить, что нужно использовать не потоки, а
>>шарную память? Боюсь, не подойдет. fork, pipe и т.п. в данном
>>случае вызваны отсутствием времени на изучение пачки графических стандартов. Если бы
>>знал, полагаю, стринга мне хватило бы.
>Эх... надо подумать... Так... задача такая: надо вывод cat отправить в
>разделяемую память, из которой его прочитать своей программой...
>Надо подумать...
>Но толку тут мало, потому что cat будет использовать каналы всё равно.
>
>Нужна объектно-ориентированная ОС для подобных задач.
>
>>не смогу ответить быстро, - у меня его нет. Если хочешь, могу
>>дать исходник для теста.
>Брось на zbl@gmail.ru, но только с бесплатного ящика какого нибудь.
>Я на этот адрес спам собираю (для научной работы по прагматическому
>анализу), а со спамом вирусы в изобилии приходят, и этот адрес широко
>
>известен среди зараженных машин по всему Миру, так что с него посыпаться
>
>вирусы (для Windoze, естессестно) могут запрасто.

исходник дам, но попозже. Не до него сейчас...

>
>>Кстати, в каком именно ..stream.h искать конструкторы?
>А я нашёл, в чём дело. И конструктор нашёл. Но сей час
>времени нет
>рассказать...

Так все-таки есть конструктор с интом?



"pipe() + ifstream()"
Отправлено Alexander S. SalieFF , 17-Июл-04 20:49 
>Так все-таки есть конструктор с интом?

Поточный конструктор вокруг файлового дескриптора - это _depricated_, и производители компилера могут его реализовывать, а могут и забить, 3ю редакцию C++ они при этом не нарушат. Так что, хоть он и есть (конструктор), лучше считать, что его нету.


"pipe() + ifstream()"
Отправлено stalker , 19-Июл-04 11:51 
>>Так все-таки есть конструктор с интом?
>
>Поточный конструктор вокруг файлового дескриптора - это _depricated_, и производители компилера могут
>его реализовывать, а могут и забить, 3ю редакцию C++ они при
>этом не нарушат. Так что, хоть он и есть (конструктор), лучше
>считать, что его нету.

А как тогда сделать поток из pipe?


"pipe() + ifstream()"
Отправлено stalker , 30-Июл-04 00:38 
>>Так все-таки есть конструктор с интом?
>
>Поточный конструктор вокруг файлового дескриптора - это _depricated_, и производители компилера могут
>его реализовывать, а могут и забить, 3ю редакцию C++ они при
>этом не нарушат. Так что, хоть он и есть (конструктор), лучше
>считать, что его нету.

... случайно залез в fstream.h (OpenBSD 3.2: /usr/include/g++)и обнаружил вот такой текст:

class ifstream : public fstreambase, public istream {
  public:
    ifstream() : fstreambase() { }
    ifstream(int fd) : fstreambase(fd) { }
    ifstream(int fd, char *p, int l) : fstreambase(fd, p, l){ } /*Deprecated*/
    ifstream(const char *name, int mode=ios::in, int prot=0664)
        : fstreambase(name, mode | ios::in, prot) { }
    void open(const char *name, int mode=ios::in, int prot=0664)
        { fstreambase::open(name, mode | ios::in, prot); }
};

Обратите внимание на какой именно конструктор косо смотрят.
Выходит, что конструктор с интом прокатывает!?
Во фришном (4.7) дистрибутиве тоже самое...
Где грабли?


"pipe() + ifstream()"
Отправлено stalker , 06-Июл-04 12:20 
>Народ!
>Подскажите как правильно сделать такое:
>
>8<-------
>int p[4];
>pipe(&p[0]); // в трубу писать
>pipe(&p[2]); // из трубы читать
>
>pid = fork();
>if(!pid) {
>    dup2(p[0],0);
>    dup2(p[3],1);
>    close(лишние дескрипторы);
>    execlp("cat", "cat", 0);
>}
>
>ofstream foo(p[1]);
>foo << (string)data;
>foo.close();
>
>// до сих пор все работает.
>// и вот тут хочется что-то типа
>
>ifstream bar(p[2]);
>bar >> data;
>
>// как правильно инициализировать поток, чтобы он за раз все данные отдал?

ответ пришел из маленького справочника, который я купил 10 (!!!) лет назад

string data;
char c;
while (bar >> c) data+=c;

чувствую, что про производительности здесь ждать не приходится ....


>
>
>waitpid(pid, .... );
>
>8<---------
>
>ЗС,
>Стас



"pipe() + ifstream()"
Отправлено SergeiZz , 08-Июл-04 13:12 
>>// как правильно инициализировать поток, чтобы он за раз все данные отдал?
>
>ответ пришел из маленького справочника, который я купил 10 (!!!) лет назад
>
>
>string data;
>char c;
>while (bar >> c) data+=c;
Здесь я неправильно понял, что значит инициализировать.
Но справочник по-страшному врёт, между прочим:
string buf;
char c= 0;
while( bar.get(c) ) buf+= c;
Не слабая разница, правда?

>чувствую, что про производительности здесь ждать не приходится ....
Нет. С производительностью всё в порядке, по крайней мере, когда не
известно, сколько символов будет прочитано. Опратор добавления символа
к string в libstdc++ реализован грамотно (супротив соответствующему ляпу
в MS VC 6.0).


"pipe() + ifstream()"
Отправлено stalker , 08-Июл-04 13:51 
>>>// как правильно инициализировать поток, чтобы он за раз все данные отдал?
>>
>>ответ пришел из маленького справочника, который я купил 10 (!!!) лет назад
>>
>>
>>string data;
>>char c;
>>while (bar >> c) data+=c;
>Здесь я неправильно понял, что значит инициализировать.
>Но справочник по-страшному врёт, между прочим:
>string buf;
>char c= 0;
>while( bar.get(c) ) buf+= c;
>Не слабая разница, правда?

справочник не врет, просто я сноску там не прочитал. По-ходу, сдвиг отличается от get() тем, что последняя "не глотает" пробелы.... Не проверял, но верю охотно.

В этом была ошибка?


>
>>чувствую, что про производительности здесь ждать не приходится ....
>Нет. С производительностью всё в порядке, по крайней мере, когда не
>известно, сколько символов будет прочитано. Опратор добавления символа
>к string в libstdc++ реализован грамотно (супротив соответствующему ляпу
>в MS VC 6.0).