Чтение онлайн

ЖАНРЫ

Разработка приложений в среде Linux. Второе издание

Троан Эрик В.

Шрифт:

Последняя возможность, требуемая для

ladsh
— перемещение задания между состоянием выполнения на переднем плане, состоянием выполнения в фоне и остановом. Это делается с помощью двух встроенных команд:
fg
и
bg
. Они являются ограниченными версиями нормальных команд оболочки, носящих те же имена. Оба принимают один параметр, являющийся номером задания, которому предшествует знак
%
(для совместимости со стандартными оболочками). Команда
fg
перемещает определенное задание на передний план, a
bg
запускает его в фоне.

Обе операции выполняются передачей

SIGCONT
каждому процессу в активизируемой группе
процессов. Поскольку этот сигнал может передаваться каждому процессу с помощью отдельных вызовов
kill
, несколько проще передать его всей группе процессов, используя отдельный вызов
kill
. Ниже приведена реализация встроенных команд
fg
и
bg
.

461: } else if (! strcmp(newJob.progs[0].argv[0], "fg") ||

462: !strcmp(newJob.progs[0].argv[0], "bg")) {

463: if (!newJob.progs[0].argv[1] || newJob.progs[0].argv[2]) {

464: fprintf(stderr,

465: "%s: ожидался в точности один аргумент\n",

466: newJob.progs[0].argv[0]);

467: return 1;

468: }

469:

470: if (sscanf(newJob.progs[0].argv[l], "%%%d", &jobNum) != 1)

471: fprintf(stderr, "%s: ошибочный аргумент '%s'\n",

472: newJob.progs[0].argv[0],

473: newJob.progs[0].argv[1]);

474: return 1;

475: }

476:

477: for (job = jobList->head; job; job = job->next)

478: if (job->jobId == jobNum) break;

479:

480: if (!job) {

481: fprintf(stderr, "%s: неизвестное задание %d\n",

482: newJob.progs[0].argv[0], jobNum);

483: return 1;

484: }

485:

486: if (* new Job.progs[0].argv [0] == 'f') {

487: /* Перевести это задание на передний план */

488:

489: if (tcsetpgrp(0, job->pgrp))

490: perror("tcsetpgrp");

491: jobList->fg = job;

492: }

493:

494: /* Перезапустить процессы в задании */

495: for (i = 0; i < job->numProgs; i++)

496: job->progs[i].isStopped = 0;

497:

498: kill (-job->pgrp, SIGCONT);

499:

500: job->stoppedProgs = 0;

501:

502: return 0;

503: }

Управление заданиями — последняя возможность примера

ladsh
, необходимая для нормального функционирования. В нем до сих пор не хватает многих свойств, присущих регулярным оболочкам, например, переменные оболочки и окружения, однако он иллюстрирует все низкоуровневые задания, выполняемые оболочками. Полный исходный код окончательной версии
ladsh
доступен в приложении Б.

Глава 16

Терминалы и псевдотерминалы

Устройства, предназначенные для интерактивного использования [107] , обладают сходным интерфейсом, который был выведен десятилетия назад для последовательных

терминалов TeleType и получил название tty. Интерфейс tty используется для доступа к последовательным терминалам, консолям, терминалам xterm, сетевым регистрационным именам и тому подобному.

Интерфейс tty прост концептуально, но сложен в реализации. Будучи гибким и мощным, он может записывать приложения, не знающие, сколько входных и выходных данных они получают, а также работать в сети, на локальном экране либо через модем. Приложения можно даже запускать без их ведома под управлением другой программы.

107

То есть устройства, используемые как для ввода, так и для вывода.

К сожалению, разработчикам Unix пришлось предпринять несколько попыток совершенствования интерфейса. Они оставили пользователям три разных интерфейса для соединения с устройствами tty. Интерфейсы sgtty (BSD) и termio (System V) теперь вытеснены интерфейсом termios (POSIX), который представляет собой супермножество команд интерфейса termio. Так как все существующие системы поддерживают интерфейс termios, и поскольку это самый мощный интерфейс, мы документируем только termios, а не ранние интерфейсы. (Ради поддержки унаследованного исходного кода Linux поддерживает termio, а также termios. Ранее он также ограниченно поддерживал интерфейс sgtty, но эта поддержка впоследствии была изъята, поскольку этот интерфейс никогда не был идеален, и в нем уже не было существенной потребности.)

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

Устройство tty имеет два конца. Если рассуждать упрощенно, один конец присоединяется к программе, а второй — к аппаратному устройству. Это верно для последовательного порта; в данном случае драйвер последовательного устройства присоединяет последовательный порт (и, таким образом, терминал или модем) к оболочке, редактору или другой программе. Это также верно для консоли; драйвер консоли соединяет клавиатуру и экран с такими же типами программ. Но в некоторых случаях на каждом конце находится по программе; при этом один из концов занимает место оборудования.

Например, при сетевом подключении один конец устройства tty соединяется с программой, предоставляющей сетевое подключение, а второй — с оболочкой, редактором или другой потенциально интерактивной программой. Если программы находятся на каждом конце, вы должны ясно понимать, на каком конце эмулируется оборудование; при сетевом подключении к сети подключается аппаратная сторона.

Устройства tty с программным обеспечением на обоих концах называются псевдотерминалами (pseudo-tty, или же просто pty). В первой части главы они рассматриваться не будут, поскольку программный конец pty обрабатывается так же, как и любое другое устройство tty. Позже мы поговорим о программировании аппаратного конца pty.

16.1. Операции tty

Устройства tty предоставляют огромное количество опций обработки данных; они относятся к наиболее сложным устройствам ядра. Настраивать можно опции обработки входных и выходных данных, а также потока данных. Также можно контролировать ограниченное манипулирование данными на уровне драйвера устройства.

Интерфейсы tty работают в двух основных режимах: неформатируемый режим и режим обработки. Неформатируемый режим передает данные в приложение без изменений. Режим обработки, известный также как канонический режим, поддерживает ограниченный построчный редактор внутри драйвера устройства и пересылает отредактированные входные данные в приложение по одной строке за раз. Этот режим изначально произрастает из универсальных систем, в которых специализированные устройства обработки входных данных предоставляли режим обработки без прерывания ЦП.

Поделиться с друзьями: