Майкл Джонсон - Разработка приложений в среде Linux. Второе издание
- Название:Разработка приложений в среде Linux. Второе издание
- Автор:
- Жанр:
- Издательство:Вильямс
- Год:2007
- Город:Москва
- ISBN:978-5-8459-1143-8
- Рейтинг:
- Избранное:Добавить в избранное
-
Отзывы:
-
Ваша оценка:
Майкл Джонсон - Разработка приложений в среде Linux. Второе издание краткое содержание
Книга известных профессионалов в области разработки коммерческих приложений в Linux представляет собой отличный справочник для широкого круга программистов в Linux, а также тех разработчиков на языке С, которые перешли в среду Linux из других операционных систем. Подробно рассматриваются концепции, лежащие в основе процесса создания системных приложений, а также разнообразные доступные инструменты и библиотеки. Среди рассматриваемых в книге вопросов можно выделить анализ особенностей применения лицензий GNU, использование свободно распространяемых компиляторов и библиотек, системное программирование для Linux, а также написание и отладка собственных переносимых библиотек. Изобилие хорошо документированных примеров кода помогает лучше усвоить особенности программирования в Linux.
Книга рассчитана на разработчиков разной квалификации, а также может быть полезна для студентов и преподавателей соответствующих специальностей.
Разработка приложений в среде Linux. Второе издание - читать онлайн бесплатно полную версию (весь текст целиком)
Интервал:
Закладка:
18: sigOrder[nextSig++] = signo;
19: }
20:
21: int main() {
22: sigset_t mask;
23: sigset_t oldMask;
24: struct sigaction act;
25: int i;
26:
27: /* Обрабатываемые в программе сигналы */
28: sigemptyset(&mask);
29: sigaddset(&mask, SIGRTMIN);
30: sigaddset(&mask, SIGRTMIN+1);
31: sigaddset(&mask, SIGUSR1);
32:
33: /* Отправить сигнал handler() и сохранять их блокированными,
34: чтобы handler() был сконфигурирован во избежание
35: состязаний при манипулировании глобальными переменными */
36: act.sa_handler = handler;
37: act.sa_mask = mask;
38: act.sa_flags = 0;
39:
40: sigaction(SIGRTMIN, &act, NULL);
41: sigaction(SIGRTMIN+1, &act, NULL);
42: sigaction(SIGUSR1, &act, NULL);
43:
44: /* Блокировать сигналы, с которыми мы работаем, чтобы
45: была видна очередность и порядок */
46: sigprocmask(SIG_BLOCK, &mask, &oldMask);
47:
48: /* Генерировать сигналы */
49: raise(SIGRTMIN+1);
50: raise(SIGRTMIN);
51: raise(SIGRTMIN);
52: raise(SIGRTMIN+1);
53: raise(SIGRTMIN);
54: raise(SIGUSR1);
55: raise(SIGUSR1);
56:
57: /* Разрешить доставку этих сигналов. Все они будут доставлены
58: прямо перед возвратом этого вызова (для Linux; это
59: НЕПЕРЕНОСИМОЕ поведение). */
60: sigprocmask(SIG_SETMASK, &oldMask, NULL);
61:
62: /* Отобразить упорядоченный список перехваченных сигналов */
63: printf("Принятые сигналы:\n");
64: for (i = 0; i < nextSig; i++)
65: if (sigOrder[i] < SIGRTMIN)
66: printf("\t%s\n", strsignal(sigOrder[i]));
67: else
68: printf("\tSIGRTMIN + %d\n", sigOrder[i] - SIGRTMIN);
69:
70: return 0;
71: }
Эта программа посылает себе некоторое количество сигналов и выводит на дисплей порядок их получения. Когда сигналы отправляются, она блокирует их, чтобы предотвратить немедленную доставку. Также она блокирует сигналы всякий раз, когда вызывается обработчик, устанавливая значение члена sa_mask
структуры struct sigaction
при настройке обработчика для каждого сигнала. Это предотвращает возможное состояние состязаний при обращении к глобальным переменным nextSig
и sigOrder
изнутри обработчика.
Запуск этой программы выдаст показанные ниже результаты.
Принятые сигналы:
User defined signal1
SIGRTMIN + 0
SIGRTMIN + 0
SIGRTMIN + 0
SIGRTMIN + 1
SIGRTMIN + 1
Это показывает, что все сигналы реального времени были доставлены, в то же время, был доставлен только один экземпляр сигнала SIGUSR1
. Вы также видите изменение порядка сигналов реального времени — все сигналы SIGRTMIN
были доставлены перед SIGRTMIN + 1
.
12.7. Дополнительные сведения о сигналах
Сигналы, которые мы обсуждали до сих пор, не несли в себе никаких данных; появление сигнала — это единственная информация, которую получает приложение. В некоторых случаях было бы неплохо знать, что послужило причиной отправки сигнала (как, например, неправильная адресация памяти, генерирующая SIGSEGV
), или же иметь возможность включить данные в сигналы, генерируемые приложением. Расширение реального времени Real Time Signals позволяет решить обе эти задачи.
12.7.1. Получение контекста сигнала
Информация о том, как и почему был сгенерирован сигнал, называется контекстом [68] До появления стандарта POSIX приложение могло обращаться к struct sigcontext за информацией того же рода, что теперь представляет siginfo_t , и термин "контекст" остался от этой старой реализации.
сигнала. Приложения, которые должны видеть этот контекст, используют обработчики сигналов, отличающиеся от нормальных. Они включают два дополнительных параметра — указатель на siginfo_t
, предоставляющий контекст сигнала, и указатель на void*
, который может быть использован некоторыми низкоуровневыми системными библиотеками [69] Этот третий параметр на самом деле указывает на структуру struct ucontext , которая позволяет процессам выполнять полное переключение контекстов в пользовательском пространстве. Данные вопросы выходят за пределы тем, рассматриваемых в настоящей книге, но это хорошо документировано в Single Unix Specification.
. Вот как выглядит полный прототип такого обработчика.
void handler(int signum, siginfo_t *siginfo, void *context);
Приложение должно указать ядру на необходимость передачи полной информации о контексте, устанавливая флаг SA_SIGINFO
члена sa_mask
структуры struct sigaction
, применяемой для регистрации обработчика сигнала. Член sa_handler
также не используется, потому что он является указателем на функцию с другим прототипом. Вместо этого новый член, sa_sigaction
, указывает на обработчик сигнала с правильным прототипом. Чтобы снизить потребление памяти, sa_handler
и sa_sigaction
разрешено использовать один и тот же участок памяти, поэтому только один из двух должен применяться в одно и то же время. Чтобы сделать это прозрачным, библиотека С определяет struct sigaction
следующим образом.
#include
struct sigaction {
union {
__sighandler_t sa_handler;
__sigaction_t sa_sigaction;
} __sigaction_handler;
sigset_t sa_mask;
unsigned long sa_flags;
};
#define sa_handler __sigaction_handler.sa_handler
#define sa_sigaction __sigaction_handler.sa_sigaction
Использование представленной комбинации объединений и макросов позволяет этим двум членам разделять одну и ту же память без необходимости усложнения с точки зрения приложений.
Структура siginfo_t
содержит информацию о том, где и почему был сгенерирован сигнал. Всем сигналам доступны два члена: sa_signo
и si_code
. Какие другие члены доступны — зависит от конкретного сигнала, и эти члены разделяют память подобно тому, как это делают члены sa_handler
и sa_sigaction
структуры struct sigaction
. Член sa_signo
содержит номер доставленного сигнала и всегда равен значению первого параметра, переданного обработчику сигнала, в то время как si_code
указывает, почему сигнал был сгенерирован, и изменяется в зависимости от номера сигнала. Для большинства сигналов он может принимать перечисленные ниже значения. [70] Существует гораздо больше значений si_code , нежели мы обсуждаем здесь, и эти значения имеют отношение к асинхронному вводу-выводу, очередям сообщений и таймерам реального времени, что выходит за границы тем, обсуждаемых в книге.
SI_USER
Приложение пространства пользователя вызвало kill()
для отправки сигнала. Примечание. Функция sigsend()
, включенная в Linux для совместимости с некоторыми системами Unix, также выдает SI_USER
.
SI_QUEUE
Приложение пространства пользователя вызвало sigqueue()
для от правки сигнала, что обсуждается в самом конце этой главы.
Интервал:
Закладка: