Категории
Самые читаемые
RUSBOOK.SU » Компьютеры и Интернет » Программирование » Программирование для Linux. Профессиональный подход - Марк Митчелл

Программирование для Linux. Профессиональный подход - Марк Митчелл

Читать онлайн Программирование для Linux. Профессиональный подход - Марк Митчелл

Шрифт:

-
+

Интервал:

-
+

Закладка:

Сделать
1 ... 52 53 54 55 56 57 58 59 60 ... 77
Перейти на страницу:

  return ptr;

}

char* xstrdup(const char* s) {

 char* copy = strdup(s);

 /* Аварийное завершение, если выделить память не удалось. */

 if (сору == NULL)

  abort();

 else

  return copy;

}

void system_error(const char* operation) {

 /* Вывод сообщения об ошибке на основании значения

    переменной errno. */

 error(operation, strerror(errno));

}

void error(const char* cause, const char* message) {

 /* Запись сообщения об ошибке в поток stderr. */

 fprintf(stderr, "%s: error: (%s) %sn", program_name,

  cause, message);

 /* Завершение программы */

 exit(1);

}

char* get_self_executable_directory() {

 int rval;

 char link_target[1024];

 char* last_slash;

 size_t result_length;

 char* result;

/* Чтение содержимого символической ссылки /proc/self/exe. */

 rval =

  readlink("/proc/self/exe", link_target,

 sizeof(link_target));

 if (rval == -1)

 /* Функция readlink() завершилась неудачей, поэтому выходим

    из программы. */

 abort();

 else

  /* Запись нулевого символа в конец строки. */

  link_target[rval] = '';

 /* Удаление имени файла,

    чтобы осталось только имя каталога. */

 last_slash = strrchr(link_target, '/');

 if (last_slash == NULL || last_slash == link_target)

 /* Формат имени некорректен. */

 abort();

 /* Выделение буфера для результирующей строки. */

 result_length = last_slash - link_target;

 result = (char*)xmalloc(result_length + 1);

 /* Копирование результата. */

 strncpy(result, link_target, result_length);

 result[result_length] = '';

 return result;

}

Приведенные здесь функции можно использовать в самых разных программах.

■ Функции xmalloc(), xrealloc() и xstrdup() являются расширенными версиями стандартных функций malloc(), realloc() и strdup(), в которые дополнительно включен код проверки ошибок. В отличие от стандартных функций, которые возвращают пустой указатель в случае ошибки, наши функции немедленно завершают работу программы, если в системе недостаточно памяти.

Раннее обнаружение нехватки памяти — хорошая идея. Если этого не делать, пустые указатели будут появляться в самых неожиданных местах программы. Ситуации, связанные с нехваткой памяти, непросто воспроизвести, поэтому их отладка будет затруднена. Ошибки выделения памяти обычно имеют катастрофические последствия для программы, так что аварийное ее завершение — вполне приемлемый вариант реакции.

■ Функция 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.

■ Функция module_close() закрывает совместно используемую библиотеку, соответствующую указанному модулю, и удаляет объект module.

В файле module.c определена также глобальная переменная module_dir. В ней записано имя каталога, в котором функция module_open() будет искать совместно используемые библиотеки.

11.2.3. Сервер

Файл server.c (листинг 11.4) представляет собой реализацию простейшего HTTP-сервера.

Листинг 11.4. (server.c) Реализация HTTP-сервера

#include <arpa/inet.h>

#include <assert.h>

#include <errno.h>

#include <netinet/in.h>

#include <signal.h>

#include <stdio.h>

#include <string.h>

#include <sys/types.h>

#include <sys/socket.h>

#include <sys/wait.h>

#include <unistd.h>

#include "server.h"

/* HTTP-ответ и заголовок, возвращаемые в случае

   успешной обработки запроса. */

static char* ok_response =

 "HTTP/1.0 100 OKn"

 "Content-type: text/htmln"

 "n";

/* HTTP-ответ, заголовок и тело страницы на случай

   непонятного запроса. */

static char* bad_request_response =

 "HTTP/1.0 400 Bad Reguestn"

 "Content-type: text/htmln"

 "n"

 "<html>n"

 " <body>n"

 "  <h1>Bad Request</h1>n"

 "  <p>This server did not understand your request.</p>n"

1 ... 52 53 54 55 56 57 58 59 60 ... 77
Перейти на страницу:
На этой странице вы можете бесплатно скачать Программирование для Linux. Профессиональный подход - Марк Митчелл торрент бесплатно.
Комментарии
Открыть боковую панель
Комментарии
Сергій
Сергій 25.01.2024 - 17:17
"Убийство миссис Спэнлоу" от Агаты Кристи – это великолепный детектив, который завораживает с первой страницы и держит в напряжении до последнего момента. Кристи, как всегда, мастерски строит