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

ЖАНРЫ

Linux программирование в примерах

Роббинс Арнольд

Шрифт:

Строки 60–70 определяют

DEFBLKSIZE
; эта часть не изменилась. Наконец, строки 72–76 возвращают размер файла, если это приемлемо. Если нет (строка 78), возвращается
DEGBLKSIZE
.

Мы действительно устранили проблему [174] , но между тем оставили на месте новую версию

optimal_bufsize
, чтобы можно было убедиться, что проблема не возникнет вновь.

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

тестирования, чтобы определить, не появилась ли сходная проблема. (До сих пор нам не приходилось просить проделать этот тест, но приятно осознавать, что мы могли бы это сделать, если бы пришлось.)

174

Переписав код управления буфером! — Примеч. автора.

15.4.2.3. Добавьте код журналирования

Часто бывает так, что программа вашего приложения работает на системе, на которой вы не можете использовать отладчик (как в случае сайта клиента). В таком случае вашей целью является возможность проверки внутреннего состояния программы, но извне. Единственным способом сделать это является заставить саму программу предоставить для вас эту информацию. Для этого существует множество способов.

• Всегда записывайте сведения в специфический файл. Это простейший способ: программа всегда записывает регистрационную информацию. Затем вы можете при возможности просмотреть файл.

Недостаток в том, что в какой-то момент регистрационный файл займет все дисковое пространство. Следовательно, у вас должны быть несколько файлов журналов, причем программа периодически должна переключаться между ними. Брайан Керниган рекомендует называть файлы журнала по дням недели:

myapp.log.sun
,
myapp.log.mon
и т.д. Преимуществом здесь является то, что вам не придется вручную удалять старые файлы; вы бесплатно получаете недельную стоимость файлов журналов.

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

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

awk
или Perl, для создания сводок и отчетов.

• В качестве альтернативы можно создать какую-нибудь разновидность XML, который является самоописывающимся и допускающим преобразование в другие форматы. (Мы не являемся большими поклонниками XML, но вас это не должно останавливать).

• Для журналирования используйте

syslog
; конечное расположение сообщений журналирования может контролироваться системным администратором, (
syslog
является довольно продвинутым интерфейсом; см. справочную страницу syslog(3)).

Выбор того, как регистрировать сведения, является, конечно, легкой частью. Трудной частью является выбор того, что регистрировать. Как и в остальных случаях разработки программ, стоит подумать, прежде чем программировать. Записывайте сведения о критических переменных. Проверьте их значения, чтобы убедиться, что они в приемлемом диапазоне или в других отношениях ведут себя, как ожидается. Записывайте исключительные условия; если появляется что-то, что не должно было, зарегистрируйте это и при возможности продолжайте исполнение.

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

15.4.2.4. Файлы отладки времени исполнения

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

или запустить ее из отладчика на системе клиента было невозможно. Главный компонент продукта запускался не непосредственно из командной строки, а опосредованно, через сценарии оболочки, которые проделывали значительную первоначальную настройку.

Чтобы заставить программу выдавать при запуске журналируемые сведения, мы пришли к идее специальных отладочных файлов. Когда файл с определенным именем находился в определенном каталоге, программа выдавала бы информационные сообщения в файл журнала, который мы могли бы затем загрузить и проанализировать. Такой код выглядит следующим образом:

struct stat sbuf;

extern int do_logging; /* инициализировано нулями */

if (stat("/path/to/magic/.file", &sbuf) == 0)

 do_logging = TRUE;

...

if (do_logging) {

 /* здесь код журналирования: открытие файла, запись, закрытие и

* т.д. * /

}

Вызов

stat
происходил для каждого задания, которое выполняла программа. Таким образом, мы могли динамически включать и отключать журналирование без необходимости останавливать и повторно запускать приложение!

Как и в случае с отладочными опциями и переменными, в этом предмете имеется множество вариаций: различные файлы, которые запускают журналирование информации о различных подсистемах, директивы отладки, добавляемые в сам отладочный файл и т.д. Как и со всеми возможностями, следует планировать схему того, что вам будет нужно, а затем чисто ее реализовывать, вместо того, чтобы набросать какой-нибудь быстрый и грязный код в 3 часа пополудни (к сожалению, довольно типичная возможность в начинающих компаниях).

ЗАМЕЧАНИЕ. Не все то золото, что блестит. Специальные отладочные файлы являются лишь одним примером методик, известных как лазейки (back doors) — один или более способов выполнения разработчиками недокументированных вещей с программой, обычно с бесчестными намерениями. В нашем примере лазейка была исключительно доброкачественной. Но беспринципный разработчик легко мог бы устроить создание и загрузку скрытой копии списка клиентов, картотеки персонала или других важных данных. По одной этой причине вы должны серьезно подумать, применима ли эта методика в вашем приложении.

15.4.2.5. Добавьте специальные ловушки для контрольных точек

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

Это большая проблема, когда вы работаете в отладчике. Если вы установите контрольную точку на вызывающую сбой процедуру, вам придется набирать команду continue и нажимать ENTER сотни или тысячи раз, чтобы привести программу в состояние перед сбоем. Это по меньшей мере утомительно и способствует появлению ошибок! Это может оказаться даже таким трудным, что вы захотите отказаться от этого, даже не начав.

Решение заключается в добавлении специальных отладочных функций «ловушек» («hook»), которые ваша программа может вызвать при приближении к интересующему вас состоянию.

Например, предположим, что вы знаете, что функция

check_salary
вызывает сбой, но лишь когда она вызвана 1427 раз. (Мы не смеемся над вами; в свое время нам пришлось наблюдать довольно странные вещи.)

Чтобы перехватить

check_salary
до того, как она завершится неудачей, создайте специальную фиктивную функцию, которая ничего не делает и просто возвращается, затем сделайте так, чтобы
check_salary
вызывала ее как раз перед 1427-м своим вызовом:

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