Книга: Программирование для Linux. Профессиональный подход
Листинг 11.8. (diskfree.c) Серверный модуль, отображающий информацию о свободном дисковом пространстве
Листинг 11.8. (diskfree.c) Серверный модуль, отображающий информацию о свободном дисковом пространстве
#include <string.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <unistd.h>
#include "server.h"
/* HTML-код начала генерируемой страницы. */
static char* page_start =
"<html>n"
" <body>n"
" <pre>n";
/* HTML-код конца генерируемой страницы. */
static char* page_end =
" </pre>n"
" </body>n"
"</html>n";
void module_generate(int fd) {
pid_t child_pid;
int rval;
/* Запись начала страницы. */
write(fd, page_start, strlen(page_start));
/* Создание дочернего процесса. */
child_pid = fork();
if (child_pid == 0) {
/* Это дочерний процесс. */
/* Подготовка списка аргументов команды df. */
char* argv[] = { "/bin/df, "-h", NULL };
/* Дублирование потоков stdout и stderr для записи данных
в клиентский сокет. */
rval = dup2(fd, STDOUT_FILENO);
if (rval == -1)
system_error("dup2");
rval = dup2(fd, STDERR_FILENO);
if (rval == -1)
system_error("dup2");
/* Запуск команды df, отображающей объем свободного
пространства в смонтированных файловых системах. */
execv(argv[0], argv);
/* Функция execv() возвращает управление в программу только
при возникновении ошибки. */
system_error("execv");
} else if (child_pid > 0) {
/* Это родительский процесс, дожидаемся завершения дочернего
процесса. */
rval = waitpid(child_pid, NULL, 0);
if (rval == -1)
system_error("waitpid");
} else
/* Вызов функции fork() завершился неудачей. */
system_error("fork");
/* запись конца страницы. */
write(fd, page_end, strlen(page_end));
}
В то время как модуль issue.so
посылает содержимое файла с помощью функции sendfile()
, данный модуль должен вызвать внешнюю команду и перенаправить результаты ее работы клиенту. Для этого модуль придерживается такой последовательности действий.
1. Сначала с помощью функции fork()
создается дочерний процесс (см. раздел 3.2.2. "Функции fork() и exec()").
2. Дочерний процесс копирует дескриптор сокета в дескрипторы STDOUT_FILENO
и STDERR_FILENO
, соответствующие стандартным потокам вывода и ошибок (см. раздел 2.1.4, "Стандартный ввод-вывод"). Это копирование осуществляется с помощью системного вызова dup2()
(см. раздел 5.4 3. "Перенаправление стандартных потоков ввода, вывода и ошибок"). Все последующие данные, записываемые в эти потоки в рамках дочернего процесса, будут направляться в сокет.
3. Дочерний процесс с помощью функции execv()
вызывает команду df -h
.
4. Родительский процесс дожидается завершения дочернего процесса, вызывая функцию waitpid()
(см. раздел 5.4 2. "Системные вызовы wait()
").
Этот модуль можно легко настроить на вызов другой системной команды.
- 11.3.3. Отображение объема свободного дискового пространства
- Листинг 10.1. (simpleid.c) Отображение идентификаторов пользователя и группы
- Листинг 15.11. Код для загрузки файла с Web-сервера
- Где я могу найти информацию для дальнейшего обучения?
- Как работает модуль оперативной памяти
- Как искать информацию в Интернете?
- Как получить исчерпывающую информацию о драйверах, установленных в системе?
- Листинг 3.1. Конфигурационный файл lilo.conf
- Листинг 3.2. Файл настройки программы inittab
- Листинг 3.3. Файл
- Листинг 3.4. Информация о конфигурации и состоянии сети
- Листинг 4.1. Файл