Книга: Разработка приложений в среде Linux. Второе издание
11.7.2. Изменения в коде
11.7.2. Изменения в коде
Как только в parseCommand()
будут правильно отражены структуры данных, то запуск команд в правильном порядке становится довольно простым при достаточном внимании к деталям. Прежде всего, мы добавляем цикл в parseCommand()
для запуска дочерних процессов, поскольку теперь их может быть множество. Прежде чем войти в цикл, мы устанавливаем nextin
и nextout
, которые являются файловыми дескрипторами, используемыми в качестве стандартных потоков ввод и вывода для следующего запускаемого процесса. Для начала мы используем те же stdin и stdout, что и оболочка.
Теперь посмотрим, что происходит внутри цикла. Основная идея описана ниже.
1. Если это финальный процесс в задании, убедиться, что nextout
указывает на stdout. В противном случае нужно подключить вывод этого задания к входному концу неименованного канала.
2. Породить новый процесс. Внутри дочернего перенаправить stdin и stdout, как указано с помощью nextin
, nextout
и всех специфицированных ранее перенаправлений.
3. Вернувшись обратно в родительский процесс, закрыть nextin
и nextout
, используемые только что запущенным дочерним процессом (если только они не являются потоками ввода и вывода самой оболочки).
4. Теперь настроить следующий процесс в задании для приема его ввода из вывода процесса, который мы только что создали (через nextin
).
Вот как эти идеи перевести на С.
365: nextin=0, nextout=1;
366: for (i=0; i<newJob.numProgs; i++) {
367: if ((i+1) < newJob.numProgs) {
368: pipe(pipefds);
369: nextout = pipefds[1];
370: } else {
371: nextout = 1;
372: }
373:
374: if (!(newJob.progs[i].pid = fork())) {
375: if (nextin != 0) {
376: dup2(nextin, 0);
377: close(nextin);
378: }
379:
380: if (nextout != 1) {
381: dup2(nextout, 1);
382: close(nextout);
383: }
384:
385: /* явное перенаправление перекрывает каналы */
386: setupRedirections(newJob.progs+i);
387:
388: execvp(newJob.progs[i].argv[0], newJob.progs[i].argv);
389: fprintf(stderr, "exec() of %s failed: %sn",
390: newJob.progs[i].argv[0],
391: strerror(errno));
392: exit(1);
393: }
394:
395: /* поместить наш дочерний процесс в группу процессов,
396: чей лидер - первый процесс канала */
397: setpgid(newJob.progs[i].pid, newJob.progs[0].pid);
398:
399: if (nextin != 0) close(nextin);
400: if (nextout != 1) close (nextout);
401:
402: /* Если больше нет процессов, то nextin - мусор,
403: но это не имеет значения */
404: nextin = pipefds[0];
Единственный код, добавленный в ladsh2.с
для обеспечения перенаправлений — это функция setupRedirections()
, код которой останется неизменным во всех последующих версиях ladsh
. Ее задача состоит в обработке спецификаторов struct redirectionSpecifier
для дочерних заданий и соответствующей модификации дочерних файловых дескрипторов. Мы рекомендуем просмотреть код этой функции в приложении Б.
- 7.3. Порядок заключения, изменения, расторжения договоров
- Скидка без изменения первоначальной цены товара
- Изменения оптимизатора, направленные на совместимость
- Другие изменения в 7-й версии InterBase
- 2. Пример создания базового отношения в записи на псевдокоде
- Часть III Конструктор речевых модулей для скриптов и стандартов продаж Изменения в продажах и требования к речевым модул...
- При попытке войти в систему Пользователю1 выдается предупреждение, что загрузился временный профиль и все сделанные изме...
- Открываю документ, распечатываю его, а при закрытии Microsoft Word уточняет, хочу ли я сохранить внесенные изменения. По...
- Дата изменения
- Нет изображения при воспроизведении видео или появляется сообщение об ошибке загрузки кодека
- Глава 3 Правило непрерывного изменения
- 11.1. А кодеков-то нет!