Книга: Разработка приложений в среде 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 для дочерних заданий и соответствующей модификации дочерних файловых дескрипторов. Мы рекомендуем просмотреть код этой функции в приложении Б.

Оглавление книги


Генерация: 1.786. Запросов К БД/Cache: 3 / 0
поделиться
Вверх Вниз