Майкл Джонсон - Разработка приложений в среде Linux. Второе издание
- Название:Разработка приложений в среде Linux. Второе издание
- Автор:
- Жанр:
- Издательство:Вильямс
- Год:2007
- Город:Москва
- ISBN:978-5-8459-1143-8
- Рейтинг:
- Избранное:Добавить в избранное
-
Отзывы:
-
Ваша оценка:
Майкл Джонсон - Разработка приложений в среде Linux. Второе издание краткое содержание
Книга известных профессионалов в области разработки коммерческих приложений в Linux представляет собой отличный справочник для широкого круга программистов в Linux, а также тех разработчиков на языке С, которые перешли в среду Linux из других операционных систем. Подробно рассматриваются концепции, лежащие в основе процесса создания системных приложений, а также разнообразные доступные инструменты и библиотеки. Среди рассматриваемых в книге вопросов можно выделить анализ особенностей применения лицензий GNU, использование свободно распространяемых компиляторов и библиотек, системное программирование для Linux, а также написание и отладка собственных переносимых библиотек. Изобилие хорошо документированных примеров кода помогает лучше усвоить особенности программирования в Linux.
Книга рассчитана на разработчиков разной квалификации, а также может быть полезна для студентов и преподавателей соответствующих специальностей.
Разработка приложений в среде Linux. Второе издание - читать онлайн бесплатно полную версию (весь текст целиком)
Интервал:
Закладка:
Добавление флага WUNTRACED
к вызову waitpid()
, ожидающему на процессах переднего плана, позволяет заметить также остановленные процессы. Когда процесс скорее останавливается, чем завершается, устанавливается флаг дочернего процесса isStopped
и увеличивается номер задания stoppedProgs
. Если все программы задания были остановлены, ladsh
снова перемещается на передний план и ожидает команды пользователя. Вот как выглядит часть главного цикла ladsh
, ожидающая на процессе переднего плана.
708: /* задание выполняется на переднем плане; ожидать его */
709: i = 0;
710: while (!jobList.fg->progs[i].pid ||
711: jobList.fg->progs[i].isStopped) i++;
712:
713: waitpid(jobList.fg->progs[i].pid, &status, WUNTRACED);
714:
715: if (WIFSIGNALED(status) &&
716: (WTERMSIG(status) != SIGINT)) {
717: printf("%s\n", strsignal(status));
718: }
719:
720: if (WIFEXITED(status) || WIFSIGNALED(status)) {
721: /* дочерний процесс завершен */
722: jobList.fg->runningProgs--;
723: jobList.fg->progs[i].pid = 0;
724:
725: if (!jobList.fg->runningProgs) {
726: /* дочерний процесс завершен */
727:
728: removeJob(&jobList, jobList.fg);
729: jobList. fg = NULL;
730:
731: /* переместить оболочку на передний план */
732: if (tcsetpgrp (0, getpid()))
733: perror("tcsetpgrp");
734: }
735: } else {
736: /* дочерний процесс остановлен */
737: jobList.fg->stoppedProgs++;
738: jobList.fg->progs[i].isStopped = 1;
739:
740: if (jobList.fg->stoppedProgs ==
741: jobList.fg->runningProgs) {
742: printf ("\n" JOB_STATUS_FORMAT,
743: jobList.fg->jobId,
744: "Остановлен", jobList.fg->text);
745: jobList.fg = NULL;
746: }
747: }
748:
749: if (!jobList.fg) {
750: /* переместить оболочку на передний план */
751: if (tcsetpgrp (0, getpid()))
752: perror("tcsetpgrp");
753: }
754: }
Подобным образом фоновые задания могут прерываться с помощью сигналов. Мы снова добавляем WUNTRACED
к waitpid()
, что проверяет состояния фоновых процессов. После остановки фонового процесса обновляются флаг isStopped
и счетчик stoppedProgs
, а в случае остановки всего задания выводится сообщение.
Последняя возможность, требуемая для 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 прост концептуально, но сложен в реализации. Будучи гибким и мощным, он может записывать приложения, не знающие, сколько входных и выходных данных они получают, а также работать в сети, на локальном экране либо через модем. Приложения можно даже запускать без их ведома под управлением другой программы.
К сожалению, разработчикам Unix пришлось предпринять несколько попыток совершенствования интерфейса. Они оставили пользователям три разных интерфейса для соединения с устройствами tty. Интерфейсы sgtty(BSD) и termio(System V) теперь вытеснены интерфейсом termios(POSIX), который представляет собой супермножество команд интерфейса termio. Так как все существующие системы поддерживают интерфейс termios, и поскольку это самый мощный интерфейс, мы документируем только termios, а не ранние интерфейсы. (Ради поддержки унаследованного исходного кода Linux поддерживает termio, а также termios. Ранее он также ограниченно поддерживал интерфейс sgtty, но эта поддержка впоследствии была изъята, поскольку этот интерфейс никогда не был идеален, и в нем уже не было существенной потребности.)
Интерфейс termios должен поддерживать не только интерактивное использование программ, но и другие виды трафика. Последовательный канал, по которому осуществляется вход в сеть через модем, можно также использовать для дозвона через модем и связи с последовательным принтером либо другим специализированным элементом оборудования.
Устройство tty имеет два конца. Если рассуждать упрощенно, один конец присоединяется к программе, а второй — к аппаратному устройству. Это верно для последовательного порта; в данном случае драйвер последовательного устройства присоединяет последовательный порт (и, таким образом, терминал или модем) к оболочке, редактору или другой программе. Это также верно для консоли; драйвер консоли соединяет клавиатуру и экран с такими же типами программ. Но в некоторых случаях на каждом конце находится по программе; при этом один из концов занимает место оборудования.
Читать дальшеИнтервал:
Закладка: