Программирование для Linux. Профессиональный подход
Шрифт:
Раннее обнаружение нехватки памяти — хорошая идея. Если этого не делать, пустые указатели будут появляться в самых неожиданных местах программы. Ситуации, связанные с нехваткой памяти, непросто воспроизвести, поэтому их отладка будет затруднена. Ошибки выделения памяти обычно имеют катастрофические последствия для программы, так что аварийное ее завершение — вполне приемлемый вариант реакции.
■ Функция
error
сообщает о фатальной ошибке, произошедшей в программе. При этом в поток stderr
записывается сообщение об ошибке, и работа программы завершается. Для ошибок, произошедших в системных вызовах или библиотечных функциях, предназначена функция system_error
, которая генерирует сообщение об ошибке на основании значения переменной errno
(см. раздел 2.2.3, "Коды ошибок системных вызовов"). ■ Функция
get_self_executable_directory
определяет каталог, в котором содержится исполняемый файл текущего процесса. Это позволяет программе находить свои внешние компоненты. Функция проверяет содержимое символической ссылки /proc/self/exe
(см. раздет 7.2.1, "Файл /proc/self
). В файле
common.c
определены также две полезные глобальные переменные. ■ Переменная
program_name
содержит имя выполняемой программы, указанное в списке аргументов командной строки (см. раздел 2.1.1, "Список аргументов"). ■ Переменная
verbose
не равна нулю, если программа работает в режиме выдачи развернутых сообщений. В таком случае многие компоненты будут записывать в поток stdout
сообщения о ходе выполнения задачи. 11.2.2. Загрузка серверных модулей
В файле
module.c
(листинг 11.3) содержится реализация динамически загружаемых серверных модулей. Загруженному модулю соответствует структура типа server_module
, который определен в файле server.h
. Листинг 11.3. (module.c) Загрузка и выгрузка серверных модулей
#include <dlfcn.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include "server.h"
char* module_dir;
struct server_module* module_open(const char* module_name) {
char* module_path;
void* handle;
void (*module_generate)(int);
struct server_module* module;
/* Формирование путевого имени библиотеки, в которой содержится
загружаемый модуль. */
module_path =
(char*)xmalloc(strlen(module_dir) +
strlen(module_name) + 2);
sprintf(module_path, "%s/%s", module_dir, module_name);
/* Попытка открыть файл MODULE_PATH как совместно используемую
библиотеку. */
handle = dlopen(module_path, RTLD_NOW);
free (module_path);
if (handle == NULL) {
/* Ошибка: либо путь не существует, либо файл не является
совместно используемой библиотекой. */
return NULL;
}
/* Чтение константы module_generate из библиотеки. */
module_generatе =
(void(*)int))dlsym(handle,
"module_generate");
/* Проверяем, найдена ли константа. */
if (module_generate == NULL) {
/* Константа отсутствует в библиотеке. Очевидно, файл не
является серверным модулем. */
dlclose(handle);
return NULL;
}
/* Выделение и инициализация объекта server_module. */
module =
(struct server_module*)xmalloc
(sizeof (struct server_module));
module->handle = handle;
module->name = xstrdup(module_name);
module->generate_function = module_generate;
/* Успешное завершение функции. */
return module;
}
void module_close(struct server_module* module) {
/* Закрытие библиотеки. */
dlclose(module->handle);
/* Удаление строки с именем модуля. */
free((char*)module->name);
/* Удаление объекта module. */
free(module);
}
Каждый модуль содержится в файле совместно используемой библиотеки (см. раздел 2.3.2, "Совместно используемые библиотеки") и должен экспортировать функцию
module_generate
. Эта функция генерирует HTML-код Web-страницы и записывает его в сокет, дескриптор которого передан ей в качестве аргумента. В файле
module.c
определены две функции. ■ Функция
module_open
пытается загрузить серверный модуль с указанным именем. Файл модуля имеет расширение .so
, так как это совместно используемая библиотека. Функция открывает библиотеку с помощью функции dlopen
и ищет в библиотеке константу module_generate
посредством функции dlsym
(описаны в разделе 2.3.6, "Динамическая загрузка и выгрузка"). Если библиотеку не удалось открыть или в ней не обнаружена экспортируемая константа module_generate
, возвращается значение NULL
. В противном случае выделяется и возвращается объект module
.
Поделиться:
Популярные книги
Цеховик. Книга 2. Движение к цели
2. Цеховик
Фантастика:
попаданцы
альтернативная история
5.00
рейтинг книги
Сильнейший Столп Империи. Книга 4
4. Сильнейший Столп Империи
Фантастика:
фэнтези
аниме
фантастика: прочее
попаданцы
5.00
рейтинг книги
Неверный
Любовные романы:
современные любовные романы
5.50
рейтинг книги
#НенавистьЛюбовь
Любовные романы:
современные любовные романы
6.33
рейтинг книги
Родословная. Том 2
2. Линия крови
Фантастика:
городское фэнтези
аниме
фэнтези
5.00
рейтинг книги
На границе империй. Том 7. Часть 5
11. Фортуна дама переменчивая
Фантастика:
боевая фантастика
космическая фантастика
попаданцы
5.00
рейтинг книги
Курсант: назад в СССР
1. Курсант
Фантастика:
попаданцы
альтернативная история
7.33
рейтинг книги
Полонянин
2. Ночь Сварога
Приключения:
исторические приключения
8.30
рейтинг книги
Последний Паладин
1. Путь Паладина
Фантастика:
фэнтези
попаданцы
аниме
5.00
рейтинг книги
Жена со скидкой, или Случайный брак
Любовные романы:
любовно-фантастические романы
8.15
рейтинг книги
Лейб-хирург
2. Зауряд-врач
Фантастика:
альтернативная история
7.34
рейтинг книги
Принадлежать им
Любовные романы:
современные любовные романы
5.00
рейтинг книги
Хроники Тириса. Книга 1
1. Хроники Тириса
Фантастика:
боевая фантастика
космическая фантастика
фантастика: прочее
6.00
рейтинг книги
Стеллар. Заклинатель
3. Стеллар
Фантастика:
боевая фантастика
8.40