// Листинг 3.5. Использование способа 1 для создания процессов
#include
#include
#include
#include
#include
#include
int main(void) {
posix_spawnattr_t Attr;
posix_spawn_file_actions_t FileActions;
char *const argv4[] = {«Task4»,...,NULL};
char *const argv5[] = {«Task5'\...,NULL};
char *const argv6[] = {«Task6»,...,NULL};
pid_t Pid;
int stat;
// Выполняем первые три задачи синхронно,
system(«Taskl . . . ") ;
system(«Task2 . . . ") ;
system(«Task3 . . . ") ;
//иниииализируем структуры
posix_spawnattr_init(&Attr);
posix_spawn_file_actions_init(&FileActions);
// execute last 3 tasks asynchronously
posix_spawn(&Pid,«Task4»,&FileActions,&Attr,argv4,NULL);
posix_spawn(&Pid,«Task5»,&FileActions,&Attr,argv5,NULL);
posix_spawn(&Pid,«Task6»,&FileActions,&Attr,argv6,NULL);
// like a good parent, wait for all your children
wait (&stat);
wait (&stat);
wait (&stat);
return(0);
}
В листинге 3.5 из функции main() с помощью функции system() вызываются на выполнение задачи Task1, Task2и Task3.Каждая из них выполняется синхронно с родительским процессом. Задачи Task4, Task5и Task6выполняются асинхронно родительскому процессу благодаря использованию функций posix__spawn(). Многоточие (... ) используется для обозначения файлов, требуемых задачам. Родительский процесс вызывает три функции wait(), и каждая из них ожидает завершения одной из задач (Task4, Task5или Task6).
Используя второй способ, программу визуализации можно запустить из сценария командной оболочки. Преимущество этого сценария состоит в том, что он позволяет использовать все команды и операторы оболочки. В нашей программе визуализации для управления выполнением задач используются метасимволы & и &&.
Task1 ... && Task2 ... && Task3 Task4 . . . & Task5 . . . & Task6
Здесь благодаря использованию метасимвола && задачи Task1, Task2и Task3выполняются последовательно при условии успешного выполнения предыдущей задачи. Задачи же Task4, Task5и Task6выполняются одновременно, поскольку использован метасимвол &. Приведем некоторые метасимволы, применяемые при разделении команд в средах UNIX/Linux, и способы выполнения этих команд.
&& Каждая следующая команда будет выполняться только в случае успешного выполнения предыдущей команды.
|| Каждая следующая команда будет выполняться только в случае неудачного выполнения предыдущей команды.
; Команды должны выполняться последовательно.
& Все команды должны выполняться одновременно.
При использовании третьего способа задачи делятся по категориям. При декомпозиции программы следует разобраться, можно ли в ней выделить различные категории задач. Например, одни задачи могут «отвечать» за интерфейс пользователя, т.е. его создание, ввод данных, вывод данных и пр. Другим задачам поручаются вычисления, управление данными и пр. Такой подход весьма полезен не только при проектировании программы, но и при ее реализации. В нашей программе визуализации мы можем разделить задачи по следующим категориям:
• задачи, которые выполняют линейные преобразованиях преобразования изображения на экране при изменении точки обзора; преобразования сцены;
• задачи, которые выполняют растеризацию: вычерчивание линий; заливка участков сплошного фона; растеризация многоугольников;
• задачи, которые выполняют удаление поверхностей: удаление скрытых поверхностей; удаление невидимых поверхностей;
• задачи, которые выполняют наложение теней: затенение отдельных пикселей; затенение изображения в целом.
Разбиение задач по категориям позволяет нашей программе приобрести более общий характер. Процессы при необходимости создают другие процессы, предназначенные для выполнения действий только определенной категории. Например, если нашей программе предстоит визуализировать лишь один объект, а не всю сцену, то нет никакой необходимости порождать процесс, который выполняет удаление скрытых поверхностей; вполне достаточно будет удаления невидимых поверхностей (одного объекта). Если объект не нужно затенять, то нет необходимости порождать задачу, выполняющую наложение тени; обязательным остается лишь линейное преобразование при решении задачи растеризации. Для запуска программы с использованием третьего способа можно использовать родительский процесс или сценарий оболочки. Родительский процесс может определить, какой нужен тип визуализации, и передать соответствующую информацию каждому из специализированных процессов, чтобы они «знали», какие процессы им следует порождать. Эта информация может быть также перенаправлена каждому из специализированных процессов из сценария оболочки. Реализация третьего способа представлена в листинге 3.6.
Читать дальше