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

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

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


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