Марк Митчелл - Программирование для Linux. Профессиональный подход
- Название:Программирование для Linux. Профессиональный подход
- Автор:
- Жанр:
- Издательство:Вильямс
- Год:2002
- Город:Москва
- ISBN:5-8459-0243-6
- Рейтинг:
- Избранное:Добавить в избранное
-
Отзывы:
-
Ваша оценка:
Марк Митчелл - Программирование для Linux. Профессиональный подход краткое содержание
Данная книга в основном посвящена программированию в среде GNU/Linux. Авторы применяют обучающий подход, последовательно излагая самые важные концепции и методики использования расширенных возможностей системы GNU/Linux в прикладных программах. Читатели научатся писать программы, к интерфейсу которых привыкли пользователи Linux; освоят такие технологии, как многозадачность, многопотоковое программирование, межзадачное взаимодействие и взаимодействие с аппаратными устройствами; смогут улучшить свои программы, сделав их быстрее, надежнее и безопаснее; поймут особенности системы GNU/Linux, ее ограничения, дополнительные возможности и специфические соглашения.
Книга предназначена для программистов, уже знакомых с языком С и имеющих базовый опыт работы в GNU/Linux.
Программирование для 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
.
#include
#include
#include
#include
#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-сервера.
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include "server.h"
/* HTTP-ответ и заголовок, возвращаемые в случае
успешной обработки запроса. */
static char* ok_response =
"HTTP/1.0 100 OK\n"
"Content-type: text/html\n"
"\n";
/* HTTP-ответ, заголовок и тело страницы на случай
непонятного запроса. */
static char* bad_request_response =
"HTTP/1.0 400 Bad Reguest\n"
"Content-type: text/html\n"
"\n"
"\n"
"
\n"
"
Bad Request
\n"
"
This server did not understand your request.
\n"
"
\n"
"
\n";
/* HTTP-ответ, заголовок и шаблон страницы на случай,
когда запрашиваемый документ не найден. */
static char* not_found_response_template =
"HTTP/1.0 404 Not Found\n"
"Content-type: text/html\n"
"\n"
"\n"
"
\n"
"
Not Found
\n"
"
The requested URL %s was not found on this server.
\n"
"
\n"
"
\n";
/* HTTP-ответ, заголовок к шаблон страницы на случай,
когда запрашивается непонятный метод */
static char* bad_method_response_template =
"HTTP/1.0 501 Method Not Implemented\n"
"Content-type: text/html\n"
"\n"
"\n"
"
\n"
"
Method Not Implemented
\n"
"
The method %s is not implemented by this server.
\n"
"
\n"
"
\n";
/* Обработчик сигнала SIGCHLD, удаляющий завершившиеся
дочерние процессы. */
static void clean_up_child_process(int signal_number) {
int status;
wait(&status);
}
/* Обработка HTTP-запроса "GET" к странице PAGE и
запись результата в файл с дескриптором CONNECTION_FD. */
static void handle_get(int connection_fd, const char* page) {
struct server_module* module = NULL;
/* Убеждаемся, что имя страницы начинается с косой черты и
не содержит других символов косой черты, так как
подкаталоги не поддерживаются. */
if (*page == '/' && strchr(page + 1, '/') == NULL) {
Интервал:
Закладка: