50 } 51
52 return(0);
53 }
В строках 21 и 25 системнал функция setenv() используется для передачи значений файловых дескрипторов сыновнему процессу. Это возможно благодаря тому, что сыновний процесс наслелует среду родительского процесса. Мы можем устанавливать переменные среды в программе с помощью вызова функции setenv(). В данном случае мы устанавливаем их следующим образом.
Fdin=filedesc; Fdout=filedesc;
Сыновний процесс затем использует системный вызов getenv() для считывания значений переменных Fdinи Fdout.Значение переменной Fdinбудет представлять «считывающий конец» канала для сыновнего процесса, а значение переменной Fdout— «записывающий». Использование системных функций setenv() и getenv()обеспечивает просгую форму межпроцессного взаимодействия (interprocess communication— IPC) между родительским и сыновним процессами. Каналы создаются при выполнении инструкций, приведенных в строке 14. Родительский процесс присоединяется к одному концу канала для операции записи с помощью метода attach()(строка29). После присоединения любые данные, помещенные в объект OPipeтипа ofstream,будут записаны в канал. Итератор типа ostream_iteratorподключается к объекгу OPipeпри выполнении следующей инструкции (строка 30):
ostream_iterator OPtr(OPipe,"\n»);
Теперь итератор OPtrссылается на объект OPipe.После каждой порции помещаемых в канал данных будет вставляться разделитель "\n».С помощью итератора OPtrмы можем поместить в канал любое количество float-значений. При этом мы можем связать с каналом несколько итераторов различных типов. Но в этом случае необходимо, чтобы на «считывающем» конце канала данные извлекались с использованием ите раторов соответствующих типов. При выполнении слелующей инструкции из программы 11.2 в канал сначала помещается количество элементов, подлежащих передаче: OPipe « X.size() « endl;
Сами элементы отправляются с использованием одного из стандартных С++-алгоритмов:
copy(X.begin() ,X.end() ,OPtr) ;
Алгоритм copy() копирует содержимое одного контейнера в контейнер, связанный с итератором приемника. Здесь итератором приемника является объект OPtr.Объект OPtrсвязан с объектом OPipe,поэтому при выполнении алгоритма copy ()(«уместившегося» в одной строке кода) в канал переписывается все содержимое контейнера. Этот пример демонстрирует возможность использования стандартных алгоритмов для организации взаимодействия между различными частями сред параллельного или распределенного программирования. Вданном случае алгоритм copy () пересылает информацию от одного процесса другому (из одного адресного пространства в другое). Эти процессы выполняются параллельно, и алгоритм copy ()значительно упрощает взаимодействие между ними. Мы подчеркиваем важность этого подхода, поскольку, если есть хоть какал-то возможность упростить логику параллельной или распределенной программы, ею нужно непременно воспользоваться. Ведь межпроцессное взаимодействие — это один из самых сложных разделов параллельного или распределенного программирования. С++-алгоритмы, библиотека классов iostreamS и итератор типа ostream_iteratorкак раз и позволяют понизить уровень сложности разработки таких программ. Использование манипулятора flush (в строке 33) гарантирует прохождение данных по каналу.
В программе 11.2.1 сыновний процесс сначала получает количество объектов, принимаемых от канала (в строке 36), а затем для считывания самих объектов использует объект IPipe класса istream.
// Программа 11.2.1
11 class multiplier{
12 float X;
13 public:
14 multiplier(float Value) { X = Value;}
15 float &operator()(float Y) { X = (X * Y);return(X);}
16 }; 17
18
19 int main(int argc,char *argv[])
20 {
21 char Value[50] ;
22 int Fd[2] ;
23 float Data;
24 vector X;
25 int NumElements;
26 multiplier N(12.2);
27 strcpy(Value,getenv(«Fdin»));
28 Fd[0] = atoi(Value);
29 strcpy(Value,getenv(«Fdout»));
30 Fd[l] = atoi(Value);
31 ifstream IPipe;
32 ofstream OPipe;
33 IPipe.attach(Fd[0]) ;
34 OPipe.attach(Fd[l]) ;
35 ostream_iterator OPtr(OPipe,"\n»);
36 IPipe » NumElements;
37 for(int N = 0;N < NumElements;N++)
38 {
39 IPipe » Data;
40 X.push_back(Data);
41 }
42 OPipe « X.size() « endl;
43 transform(X.begin(),X.end(),OPtr,N);
Читать дальше