Книга: Системное программирование в среде Windows

Внутрипроцессные серверы

Внутрипроцессные серверы

Как ранее уже отмечалось, основное усовершенствование программы serverSK связано с включением в нее внутрипроцессных серверов. В программе 12.3 показано, как написать библиотеку DLL, обеспечивающую услуги подобного рода. В программе представлены две уже известные вам функции — функция, осуществляющая подсчет слов, и функция toupper.

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

• Функции никоим образом не должны изменять окружение процесса. Например, если одна из функций изменит рабочий каталог, то это окажет воздействие на весь процесс.

• Аналогично, функции не должны перенаправлять стандартный ввод и вывод.

• Такие ошибки программирования, как выход индекса или указателя за пределы отведенного диапазона или переполнение стека, могут приводить к порче памяти, относящейся к другому потоку или самому процессу. 

• Утечка ресурсов, возникшая, например, в результате того, что системе не была своевременно возвращена освободившаяся память или не были закрыты дескрипторы, в конечном счете, окажет отрицательное воздействие на работу всей серверной системы.

Столь жесткие требования не предъявляются к процессам по той причине, что один процесс, как правило, не может нанести ущерб другим процессу, а после того, как процесс завершает свое выполнение, занимаемые им ресурсы автоматически освобождаются. В связи с этим служба, как правило, разрабатывается и отлаживается как поток, и лишь после того, как появится уверенность в надежности ее работы, она преобразуется в DLL.

В программе 12.3 представлена небольшая библиотека DLL, включающая две функции.

Программа 12.3. command: пример внутри процессных серверов 

/* Глава 12. commands.с. */
/* Команды внутрипроцессного сервера для использования в serverSK и так далее. */
/* Имеется несколько команд, реализованных в виде библиотек DLLs. */
/* Функция каждой команды принимает два параметра и обеспечивает */
/* безопасное выполнение в многопоточном режиме. Первым параметром */
/* является строка: команда arg1 arg2 … argn */
/* (то есть обычная командная строка), а вторым – имя выходного файла. … */
static void extract_token(int, char *, char *);
_declspec(dllexport)
int wcip(char * command, char * output_file)
/* Счетчик слов; внутрипроцессный. */
/* ПРИМЕЧАНИЕ: упрощенная версия; результаты могут отличаться от тех, которые обеспечивает утилита wc. */
{
 extract_token(1, command, input_file);
 fin = fopen(input_file, "r");
 /* … */
 ch = nw = nc = nl = 0;
 while ((c = fgetc(fin)) != EOF) {
  /* … Стандартный код — для данного примера не является существенным … */
 }
 fclose(fin);
 /* Записать результаты. */
 fout = fopen(output_file, "w");
 if (fout == NULL) return 2;
 fprintf(fout, " %9d %9d %9d %sn", nl, nw, nc, input_file);
 fclose(fout);
 return 0;
}
_declspec(dllexport)
int toupperip(char * command, char * output_file)
/* Преобразует входные данные к верхнему регистру; выполняется внутри процесса. */
/* Вторая лексема задает входной файл (первая лексема – "toupperip"). */
{
 /* … */
 extract_token(1, command, input_file);
 fin = fopen(input_file, "r");
 if (fin == NULL) return 1;
 fout = fopen(output_file, "w");
 if (fout == NULL) return 2;
 while ((c = fgetc (fin)) != EOF) {
  if (c == '') break;
  if (isalpha(c)) с = toupper(c);
  fputc(c, fout);
 }
 fclose(fin);
 fclose(fout);
 return 0;
}
static void extract_token(int it, char * command, char * token) {
 /* Извлекает из "команды" лексему номер "it" (номером первой лексемы */
 /* является "0"). Результат переходит в "лексему" (token) */
 /* В качестве разделителей лексем используются пробелы. … */
 return;
}
 

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


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