Книга: Программирование для 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()").

Этот модуль можно легко настроить на вызов другой системной команды.

Оглавление книги

Похожие страницы

Генерация: 0.157. Запросов К БД/Cache: 5 / 0
поделиться
Вверх Вниз