Майкл Джонсон - Разработка приложений в среде Linux. Второе издание
- Название:Разработка приложений в среде Linux. Второе издание
- Автор:
- Жанр:
- Издательство:Вильямс
- Год:2007
- Город:Москва
- ISBN:978-5-8459-1143-8
- Рейтинг:
- Избранное:Добавить в избранное
-
Отзывы:
-
Ваша оценка:
Майкл Джонсон - Разработка приложений в среде Linux. Второе издание краткое содержание
Книга известных профессионалов в области разработки коммерческих приложений в Linux представляет собой отличный справочник для широкого круга программистов в Linux, а также тех разработчиков на языке С, которые перешли в среду Linux из других операционных систем. Подробно рассматриваются концепции, лежащие в основе процесса создания системных приложений, а также разнообразные доступные инструменты и библиотеки. Среди рассматриваемых в книге вопросов можно выделить анализ особенностей применения лицензий GNU, использование свободно распространяемых компиляторов и библиотек, системное программирование для Linux, а также написание и отладка собственных переносимых библиотек. Изобилие хорошо документированных примеров кода помогает лучше усвоить особенности программирования в Linux.
Книга рассчитана на разработчиков разной квалификации, а также может быть полезна для студентов и преподавателей соответствующих специальностей.
Разработка приложений в среде Linux. Второе издание - читать онлайн бесплатно полную версию (весь текст целиком)
Интервал:
Закладка:
20:
21: act.sa_sigaction = handler;
22: sigemptyset(&act.sa_mask);
23: act.sa_flags = SA_SIGINFO;
24: sigaction(SIGSEGV, &act, NULL);
25:
26: *((int *)NULL) = 1 ;
27:
28: return 0;
29: }
12.7.2. Отправка данных с сигналом
Механизм siginfo_t
также позволяет сигналам, которые посылают программы, присоединять к себе один элемент данных (этот элемент может быть указателем, что позволяет неявно передавать любой необходимый объем данных). Чтобы отправить данные, используется union sigval
.
#include
union sigval {
int sival_int;
void *sival_ptr;
};
Любой из членов объединения — sival_int
или sival_ptr
— может быть установлен в требуемое значение, которое включается в siginfo_t
, доставляемое вместе с сигналом. Чтобы сгенерировать сигнал с union sigval
, должна использоваться функция sigqueue()
.
#include
void *sigqueue(pid_t pid, int signum, const union sigval value);
В отличие от kill()
, pid
должен быть корректным идентификатором процесса (отрицательные значения не допускаются), signum
указывает номер посылаемого сигнала. Подобно kill()
, sigqueue()
допускает нулевое значение signum
нулю, чтобы проверить, позволяет ли вызывающий процесс посылать целевому сигналы, в действительности не выполняя такой посылки. Последний параметр, value
, представляет собой элемент данных, передаваемый вместе с сигналом.
Чтобы принять union sigval
, процесс, перехватывающий сигнал, должен использовать SA_SIGINFO
при регистрации обработчика сигналов с помощью sigaction()
. Когда член si_code
структуры siginfo_t
равен SI_QUEUE
, то siginfo_t
представляет член si_value
, который содержит значение value
, переданное sigqueue
.
Ниже приведен пример отправки элемента данных с сигналом. Он устанавливает в очередь три сигнала SIGRTMIN
с разными элементами данных. Он демонстрирует, что сигналы доставляются в том же порядке, что были отправлены, как мы и ожидаем при работе с сигналами реального времени [73] Дополнительные примеры обработки сигналов вы можете найти в программах для аренды файлов (глава 13), управления терминалом (глава 16) и работы с интервальными таймерами (глава 18).
. Более сложный пример, использующий сигналы для отслеживания изменений в каталогах, можно найти в главе 14.
1: /* sigval.с */
2:
3: #include
4: #include
5: #include
6: #include
7: #include
8:
9: /* Захватить сигнал и зарегистрировать факт его обработки */
10: void handler(int signo, siginfo_t *si, void *context) {
11: printf("%d\n", si->si_value.sival_int);
12: }
13:
14: int main() {
15: sigset_t mask;
16: sigset_t oldMask;
17: struct sigaction act;
18: int me = getpid();
19: union sigval val;
20:
21: /* Отправить сигналы handler() и сохранять все сигналы заблокированными,
22: чтобы handler() был сконфигурирован для перехвата с исключением
23: состязаний при манипулировании глобальными переменными */
24: act.sa_sigaction = handler;
25: act.sa_mask = mask;
26: act.sa_flags = SA_SIGINFO;
27:
28: sigaction(SIGRTMIN, &act, NULL);
29:
30: /* Блокировать SIGRTMIN, чтобы можно было увидеть очередь и упорядочение*/
31: sigemptyset(&mask);
32: sigaddset(&mask, SIGRTMIN);
33:
34: sigprocmask(SIG_BLOCK, &mask, &oldMask);
35:
36: /* Сгенерировать сигналы */
37: val.sival_int = 1;
38: sigqueue(me, SIGRTMIN, val);
39: val.sival_int++;
40: sigqueue(me, SIGRTMIN, val);
41: val.sival_int++;
42: sigqueue(me, SIGRTMIN, val);
43:
44: /* Разрешить доставку сигналов */
45: sigprocmask(SIG_SETMASK, &oldMask, NULL);
46:
47: return 0;
48: }
Глава 13
Расширенная обработка файлов
В Linux файлы применяются при решении большого количества задач, среди которых, например, хранение долговременных данных, организация сетей с помощью сокетов и доступ к устройствам посредством файлов устройств. Разнообразие приложений, работающих с файлами, привело к созданию множества специальных способов управления файлами. В главе 11 рассматривались наиболее распространенные действия с файлами; в настоящей же главе исследуются специализированные файловые операции. В частности, мы рассмотрим следующие вопросы: использование одновременно нескольких файлов, отображение файлов на системную память, блокировка файлов, чтение и запись вразброс.
13.1. Мультиплексирование входных и выходных данных
Многим клиент-серверным приложениям необходимо считывать входные данные или записывать выходные данные с помощью одновременно нескольких файловых дескрипторов. Например, современные Web-браузеры открывают одновременно несколько сетевых подключений, чтобы уменьшить время загрузки Web-страницы. Это позволяет им загружать множество изображений, имеющихся на большинстве Web-страниц, быстрее, чем с помощью последовательных подключений. Кроме канала межпроцессных взаимодействий (IPC), используемого графическими браузерами для связи с X-сервером, на котором они отображаются, браузеры работают с множеством файловых дескрипторов.
Браузеру легче всего обработать эти файлы, считывая и обрабатывая данные из них (системный вызов read()
в сетевом подключении, так же, как и в канале, возвращает доступные в настоящий момент данные и блокирует их только в случае неготовности). Этот подход эффективен, пока все подключения доставляют данные достаточно регулярно.
Если одно из сетевых подключений является медленным, начинают возникать проблемы. Когда браузер снова считывает из этого файла, он перестает работать, в то время как read()
блокируется в ожидании поступления данных. Не стоит и упоминать, что подобное поведение не является удобоваримым для пользователя браузера.
Для иллюстрации этих проблем рассмотрим короткую программу, считывающую из двух файлов, p1
и p2
. Для ее испытания откройте три сеанса работы с X-терминалом (или воспользуйтесь тремя виртуальными консолями). Создайте каналы под именами p1
и p2
(с помощью команды mknod
), затем запустите cat > p1
и cat > p2
в двух терминалах, одновременно запустив mpx-blocks
в третьем. После этого набирайте любой текст в каждом окно cat
и смотрите, как он появляется. Помните, что две команды cat
не будут записывать данные в каналы до конца строки.
1: /* mpx-blocks.с */
2:
3: #include
4: #include
5: #include
6:
7: int main(void) {
8: int fds[2];
9: char buf[4096];
10: int i;
11: int fd;
12:
13: if ((fds[0] = open("p1", O_RDONLY) ) < 0) {
14: perror("open p1");
Интервал:
Закладка: