Читаем Linux программирование в примерах полностью

На системе BSD или GNU/Linux обработчик сигнала не должен дополнительно использовать 'signal(signum, handler)' для переустановки обработчика. Однако, лишний вызов не причиняет никакого вреда, поэтому сохраняется статус-кво.

В действительности, POSIX предоставляет функцию bsd_signal(), которая идентична signal() за тем исключением, что она гарантирует, что обработчик сигнала останется установленным:

#include /* XSI, устаревает */

void (*bsd_signal(int sig, void (*func)(int)))(int);

Это устраняет проблемы переносимости. Если вы знаете, что ваша программа будет работать лишь на системах POSIX, вы можете воспользоваться bsd_signal() вместо signal().

Одно предостережение — эта функция также помечена как «устаревающая», что означает возможность отказа от нее в будущем стандарте. На практике, даже если от нее откажутся, поставщики скорее всего долгое время будут ее поддерживать. (Как мы увидим, функция API POSIX sigaction() предоставляет достаточно возможностей для написания рабочей версии, если это вам нужно.)

<p>10.4.3. Игнорирование сигналов</p>

Более практично, когда вызывается обработчик сигнала, это означает, что программа должна завершиться и выйти. Было бы раздражающим, если бы большинство программ по получении SIGINT выводили бы сообщение и продолжали работу; смысл сигнала в том, что они должны остановиться!

Например, рассмотрите программу sort. sort, возможно, создала любое число временных файлов для использования на промежуточных этапах процесса сортировки. По получении SIGINT, sort должна удалить временные файлы и выйти. Вот упрощенная версия обработчика сигнала из GNU Coreutils sort.c:

/* Обработка прерываний и отсоединений. Упрощена для представления */

static void sighandler(int sig) {

 signal(sig, SIG_IGN); /* Отныне этот сигнал игнорировать */

 cleanup();            /* Очистка после себя */

 signal(sig, SIG_DFL); /* Восстановление действия по умолчанию */

 raise(sig);           /* Повторно отправить сигнал */

}

Установка действия SIG_IGN гарантирует, что все последующие появляющиеся сигналы SIGINT не повлияют на продолжающийся процесс очистки. Когда функция cleanup() завершит работу, восстановление действия SIG_DFL позволяет системе сделать снимок образа процесса, если это нужно возникшему сигналу. Вызов raise() восстанавливает сигнал. Затем восстановленный сигнал вызывает действие по умолчанию, которое, скорее всего, завершит программу. (Далее в этой главе мы полностью покажем обработчик сигнала sort.c.)

<p>10.4.4. Системные вызовы, допускающие повторный запуск</p>

Значение EINTR для errno (см. раздел 4.3 «Определение ошибок») указывает, что системный вызов был прерван. Хотя с этим значением ошибки может завершаться большое количество системных вызовов, двумя наиболее значительными являются read() и write(). Рассмотрите следующий код:

void handler(int signal) { /* обработка сигналов */ }

int main(int argc, char **argv) {

 signal(SIGINT, handler);

 ...

 while ((count = read(fd, buf, sizeof buf)) > 0) {

  /* Обработка буфера */

 }

 if (count == 0)

  /* конец файла, очистка и т.п. */

 else if (count == -1)

  /* ошибка */

 ...

}

Предположим, что система успешно прочла (и заполнила) часть буфера, когда возник SIGINT. Системный вызов read() еще не вернулся из ядра в программу, но ядро решает, что оно может доставить сигнал. Вызывается handler(), запускается и возвращается в середину read(). Что возвратит read()?

В былые времена (V7, более ранние системы System V) read() возвратила бы -1 и установила бы errno равным EINTR. Не было способа сообщить, что данные были переданы. В данном случае V7 и System V действуют, как если бы ничего не случилось: не было перемещений данных в и из буфера пользователя, и смещение файла не было изменено. BSD 4.2 изменила это. Были два случая:

Медленные устройства

Перейти на страницу:

Похожие книги

1С: Бухгалтерия 8 с нуля
1С: Бухгалтерия 8 с нуля

Книга содержит полное описание приемов и методов работы с программой 1С:Бухгалтерия 8. Рассматривается автоматизация всех основных участков бухгалтерии: учет наличных и безналичных денежных средств, основных средств и НМА, прихода и расхода товарно-материальных ценностей, зарплаты, производства. Описано, как вводить исходные данные, заполнять справочники и каталоги, работать с первичными документами, проводить их по учету, формировать разнообразные отчеты, выводить данные на печать, настраивать программу и использовать ее сервисные функции. Каждый урок содержит подробное описание рассматриваемой темы с детальным разбором и иллюстрированием всех этапов.Для широкого круга пользователей.

Алексей Анатольевич Гладкий

Программирование, программы, базы данных / Программное обеспечение / Бухучет и аудит / Финансы и бизнес / Книги по IT / Словари и Энциклопедии
1С: Управление торговлей 8.2
1С: Управление торговлей 8.2

Современные торговые предприятия предлагают своим клиентам широчайший ассортимент товаров, который исчисляется тысячами и десятками тысяч наименований. Причем многие позиции могут реализовываться на разных условиях: предоплата, отсрочка платежи, скидка, наценка, объем партии, и т.д. Клиенты зачастую делятся на категории – VIP-клиент, обычный клиент, постоянный клиент, мелкооптовый клиент, и т.д. Товарные позиции могут комплектоваться и разукомплектовываться, многие товары подлежат обязательной сертификации и гигиеническим исследованиям, некондиционные позиции необходимо списывать, на складах периодически должна проводиться инвентаризация, каждая компания должна иметь свою маркетинговую политику и т.д., вообщем – современное торговое предприятие представляет живой организм, находящийся в постоянном движении.Очевидно, что вся эта кипучая деятельность требует автоматизации. Для решения этой задачи существуют специальные программные средства, и в этой книге мы познакомим вам с самым популярным продуктом, предназначенным для автоматизации деятельности торгового предприятия – «1С Управление торговлей», которое реализовано на новейшей технологической платформе версии 1С 8.2.

Алексей Анатольевич Гладкий

Финансы / Программирование, программы, базы данных