
- •Операционные системы для программиста
- •Введение
- •1. Основные понятия
- •1.1. Понятие операционной системы
- •1.2. Системные соглашения для доступа к функциям ос
- •1.3. Особенности разработки программ в базовых ос
- •1.4. Командный интерфейс пользователя в ос
- •1.5. Информация об ошибках системной функции
- •2. Программный доступ к файловой системе
- •2.1. Понятия дескрипторов, идентификаторов и хэндлов
- •2.2. Ввод и вывод в стандартные файлы.
- •2.3. Базовые средства использования файлов
- •2.4. Многопользовательская блокировка файлов
- •2.5. Установка произвольной позиции в файле
- •3. Принципы построения ос
- •3.1. Модульная структура построения ос
- •3.2. Использование прерываний в ос
- •3.3. Управление системными ресурсами
- •3.4 Строение ядра операционной системы
- •3.5. Структура операционной системы типа Windows nt
- •4. Многофункциональный консольный вывод
- •4.1. Функции управления курсором
- •4.2. Многократный вывод символов и атрибутов
- •4.3. Вывод в произвольную позицию экрана
- •4.4. Ввод данных, размещенных предварительно на экране
- •5. Системные функции ввода для консольных устройств
- •5.1. Системные функции ввода текстовых строк
- •5.2. Событийно-управляемый ввод
- •5.3. Системные функции ввода с клавиатуры
- •5.4. Опрос ввода с клавиатуры в программе
- •5.5. Системные функции мыши для текстового режима
- •6. Файловые системы
- •6.1. Структуры файловых систем для пользователя
- •6.2. Методы распределения внешней памяти
- •6.3. Принципы построения файловых систем типа fat
- •6.4. Современные модификации файловой системы fat
- •6.5. Особенности построения файловой системы hpfs
- •6.6. Принципы построения файловой системы ntfs
- •6.7. Особенности строения файловых систем для Unix
- •6.8. Программный опрос файловой системы
- •7. Обеспечение множественности процессов
- •7.1. Основные понятия теории вычислительных процессов
- •7.2. Программное порождение процессов
- •7.3. Уничтожение процессов
- •7.4. Ожидание завершения процессов
- •8. Многопоточное функционирование ос
- •8.1. Понятие нити и связь Хе с процессом
- •8.2. Создание нитей (thread) в программе
- •8.3. Уничтожение нитей
- •8.4. Приостановка и повторный запуск нити
- •8.5. Ожидание завершения нити
- •9. Средства взаимодействия программных единиц
- •9.1. Абстрактные критические секции
- •9.2. Абстрактные семафоры
- •9.3. Семафоры взаимоисключения
- •9.4. Семафоры событий
- •9.5. Средства группового ожидания
- •9.6. Программные критические секции
- •9.7. Программные семафоры с внутренним счетчиком
- •10. Управление памятью
- •10.1. Виртуальная память
- •10.2. ЏодкРчка страниц для реализациШ виртуальной памяти
- •10.3. Системные функции распределения памяти
- •10.4. Совместное использование памяти
- •10.5. Отображение файлов в оперативную память
- •10.6. Динамически распределяемая память
- •11. Средства коммуникации процессов
- •11.1. Неименованные коммуникационные каналы Unix
- •11.2. Переназначение хэндлов для доступа к каналу
- •11.3. Неименованные каналы в Windows
- •11.4. Именованные каналы в Windows nt
- •11.5. Именованные каналы в Unix
- •12. Взаимодействие пользователя с ос
- •12.1. Интерфейсы операционных систем
- •12.2. Командные и операционные оболочки (shells)
- •12.3. Основные команды базовых операционных систем
- •12.4. Групповое выполнение и фоновый запуск команд
- •12.5. Стандартный ввод-вывод и конвейеры командной строки
- •12.6. Командные файлы и сценарии
- •Библиографический список
11.3. Неименованные каналы в Windows
Для создания неименованных каналов в Windows NT (и Windows 9x) предназначена системная функция CreatePipe, имеющая прототип
BOOL CreatePipe(HANDLE* phReadPipe, HANDLE* phWritePipe,
LPSECURITY_ATTRIBUTES pAttributes, DWORD nSize ),
где phReadPipe – адрес переменной для хэндла чтения из канала, phWritePipe – адрес переменной для хэндла записи в канал, pAttributes – адрес атрибутов защиты, nSize – число байтов, резервируемых для канала.
Для манипуляций с хэндлами стандартного ввода и вывода в Windows можно использовать не только универсальную функцию DuplicateHandle копирования хэндлов (которая здесь предназначена для копирования хэндлов любых объектов ядра, а не только файлов), но и более простую специализированную функцию SetStdHandle. Она позволяет построить строку таблицы соответствия для стандартного ввода или вывода в строке таблицы соответствия, явно указываемой номером хэндла. Эта функция имеет прототип
BOOL SetStdHandle(DWORD nStdHandle, HANDLE hHandle),
где nStdHandle – условное обозначение хэндла стандартного ввода, вывода или ошибок, задаваемое одной из символических констант STD_INPUT_HANDLE, STD_OUTPUT_HANDLE, STD_ERROR_HANDLE. Аргумент hHandle задает хэндл для той строки таблицы соответствия, на место которой копируется строка таблицы соответствия для хэндла стандартного ввода или вывода.
В листингах 11.3.1 и 11.3.2 приведены программы родительского и дочернего процессов, которые демонстрируют использование неименованных каналов в Windows.
#include <stdio.h>
#include <windows.h>
#define PIPESIZE 16
int main()
{HANDLE hW, hR, hstdout;
DWORD rc, cbRead;
STARTUPINFO si;
PROCESS_INFORMATION pi;
DWORD CreationFlags;
char bufread[PIPESIZE]="-";
hstdout = GetStdHandle(STD_OUTPUT_HANDLE);
if(!CreatePipe(&hR, &hW, NULL, PIPESIZE))
{printf("Error create Pipe\n");getchar();exit(1);};
SetStdHandle(STD_OUTPUT_HANDLE, hW);
memset(&si, 0, sizeof(STARTUPINFO));
si.cb=sizeof(si);
CreationFlags = NORMAL_PRIORITY_CLASS | CREATE_NEW_CONSOLE;
rc=CreateProcess(NULL, "childpip.exe", NULL, NULL, TRUE, //наследуемые
CreationFlags, NULL, NULL, &si, &pi);
if (!rc)
{printf("Error create Process, codeError = %ld\n",
GetLastError()); getchar(); return 0;
}
CloseHandle(hW);
do
{rc=ReadFile(hR, bufread, 4, &cbRead, NULL);
if (!rc)
{rc=GetLastError();
if (rc= =ERROR_BROKEN_PIPE) break;
else {printf("Error ReadFile, rc=%d\n", rc); }
}
Sleep(1000);
WriteFile(hstdout, bufread,cbRead,&cbRead,NULL);
} while (cbRead!=0);
printf("\nEnd work with pipe\n");
CloseHandle(hstdout);
CloseHandle(hR);
return 0;
}
Листинг 11.3.1. Программа родительского процесса
#include <stdio.h>
#include <windows.h>
int main()
{int step=0;
DWORD cb;
int portion=9;
char text[ ]="У лукоморья дуб зеленый, златая цепь на дубе том.";
char *ptxt=text, *textend=text+sizeof(text)-2;
HANDLE hstdout;
hstdout = GetStdHandle(STD_OUTPUT_HANDLE);
ptxt=text;
while(ptxt<=textend)
{if (ptxt>textend-portion) portion=textend-ptxt+1; //last portion may be less than 9
fprintf(stderr,"----I am Child ... (step=%d)\n\r", ++step);
WriteFile(hstdout, ptxt, portion ,&cb, NULL);
ptxt+=portion;
Sleep(2000);
}
CloseHandle(hstdout);
return 0;
}
Листинг 11.3.2. Программа childpip.exe дочернего процесса
Получение данных через канал в Windows имеет свои особенности. Попытка чтения данных из канала, передающий конец в котором закрыт, приводит не к нулевому числу прочитанных байтов, а к возвращаемому функцией ReadFile значению FALSE. Тем самым как бы фиксируется ошибка. При этом функция GetLastError() возвращает значение символической константы ERROR_BROKEN_PIPE (равное 109). Нормально построенная программа чтения данных из канала должна распознавать это значение как обычное завершение данных в канале аналогично концу файла. Именно так построена программа последнего примера.
Заметим, что в программе родительского процесса при создании дочернего процесса использован параметр наследования (пятый аргумент функции CreateProcess), равный TRUE. Это значение заставляет дочерний процесс унаследовать все дескрипторы открытых объектов и соответственно хэндлы этих дескрипторов.