Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
СПиОС.doc
Скачиваний:
3
Добавлен:
07.07.2019
Размер:
252.42 Кб
Скачать
  1. Формат команд процессора 80386. Способы адресации, которые применяются в командах процессора 80386.

Процессор 80386 содержит 240 базовых команд, часть из которых имеют модификаци. Машинные команды ПК занимают от 1 до 6 байтов.Код операции (КОП) занимает один или два первых байта команды. Кроме того для некоторых операций КОП уточняется во втором байте. Во втором байте также указываются типы операндов и способы их адресации. В остальных байтах команды указываются ее операнды. По числу обрабатываемых операндов команды делятся на 0, 1 и 2-х адресные. Существует 3 источника операндов:

  • память m;

  • регистр r;

  • тело команды data.

Рассмотрим наиболее общий формат 2-х операндной команды:

Первый байт: код операции:

 d - поле направления передачи (d=1 – в МП, d=0 – из МП;

 w - поле слова (1-команда оперирует словом, 0 – байтом);

Второй байт (постбайт) – байт режима адресации.

d

w

 

0

0

Байт из регистра в память или из регистра в регистр

0

1

Слово из регистра в память или из регистра в регистр

1

0

Байт в регистр из памяти или в регистр из регистра

1

1

Слово в регистр из памяти или в регистр из регистра

Поле mod и r/m совместно кодируют коды адреса операнда, находящегося в памяти или регистре.

Поле reg определяет второй операнд, обязательно находящийся в регистре.

Поле mod определяет используемый режим адресации. В частности оно показывает, как интерпретируется поле r/m для нахождения первого операнда.

Способ кодирования

Поле reg (r/m)

8-ми битные регистры

16-ти битные регистры

000

AL

AX

001

CL

CX

010

DL

DX

011

BL

BX

100

AH

SP

101

CH

BP

110

DH

SI

111

BH

DI

mod

смещение

00

disp=0 (в памяти)

01

disp=dispL (в памяти)

10

disp=(dispH,dispL) (в памяти)

11

в регистре

Поле r/m кодирует способ косвенной адресации.

Поле r/m

Эффективный адрес

000

EA=(BX)+(SI)+disp

001

EA=(BX)+(DI)+disp

010

EA=(BP)+(SI)+disp

011

EA=(BP)+(DI)+disp

100

EA=       +(SI)+disp

101

EA=       +(DI)+disp

110

EA=(BP)+      +disp

111

EA=(BX)+     +disp

Исключение: Если mod=00 и r/m =110, то EA=(dispH,dispL) – абсолютный адрес в памяти.

r/m

mod

00

01

10

11

w=0

w=1

000

(BX)+(SI)

(BX)+(SI)+D8

(BX)+(SI)+D16

AL

AX

001

(BX)+(DI)

(BX)+(DI)+D8

(BX)+(DI)+D16

CL

CX

010

(BP)+(SI)

(BP)+(SI)+D8

(BP)+(SI)+D16

DL

DX

011

(BP)+(DI)

(BP)+(DI)+D8

(BP)+(DI)+D16

BL

BX

100

(SI)

(SI)+D8

(SI)+D16

AH

SP

101

(DI)

(DI)+D8

(DI)+D16

CH

BP

110

D16

(BP)+D8

(BP)+D16

DH

SI

111

(BX)

(BX)+D8

(BX)+D16

BH

DI

Рассмотрим 2-х операндную команду с непосредственным операндом.Mov r/m, data (напр. Mov DX, 5 )

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

s

w

описание

х

0

один байт данных dataL

0

1

два байта данных (dataH,dataL)

1

1

один байт данных, который расширяется со знаком до 16-ти бит

Режимы адресации

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

Режимы адресации, направлены на достижение следующих целей:

  • определение адреса памяти наименьшим числом бит, что сокращает длину команд

  • вычисление адреса относительно текущей команды (так называемая относительная адресация), обеспечивающее загрузку программ без модификации в любую область памяти;

  • осуществление доступа к ячейкам памяти, адреса которых вычисляются при выполнении программы, что упрощает доступ к регулярным структурам данных;

  • оперирование адресами в такой форме, которая наиболее удобна для таких структур данных, как массивы и стеки.

Назначением режима адресации является указание способа формирования эффективного (или исполнительного) адреса ЕА. Этот адрес является либо адресом операнда (в командах, оперирующих данными), либо адресом перехода (в командах передачи управления). Полный (физический) адрес памяти формируется с привлечением одного из сегментных регистров.

Режимы адресации подразделяются на прямые и косвенные. При прямой адресации эффективный адрес либо содержится в команде, либо вычисляется с использованием значения, находящегося в команде, и содержимого, указанного в команде регистра (или двух регистров). При косвенной адресации эффективный адрес в команде определяет регистр или ячейку памяти, содержащую окончательный эффективный адрес.

  1. Защищенный режим работы микропроцессора. Адресация в защищенном режиме. Дескрипторные таблицы. Формат дескриптора сегмента. Модель памяти flat.

Недостатки реального режима:

1) процессор не способен адресоваться к памяти выше границы первого M;

  1. т.к. для адресации использ 16-битное смещение, невозможно работать с массивами более 65536 байт;

  2. поддерживается выполнение только одной программы.

Защищенный режим появился впервые в МП 286, но в полном объеме реализован в МП 386. В ЗР можно адресоваться к участку памяти размером 4Г как к одному непрерывному массиву.Для облегчения переключения в ЗР был предложен ряд интерфейсов (DPMI интерфейс).Для обеспечения совместной работы нескольких задач необходимо защитить эти задачи от взаимного влияния. Каждая задача занимает один или несколько сегментов. В ЗР каждый сегмент должен характеризоваться следующими атрибутами:

1) расположение сегмента в памяти; 2) размер сегмента; 3)уровень привилегий; 4)назначение сегмента.

Адресация в ЗР: адрес складывается из адреса начала сегмента и относительного смещения. Адрес начала сегмента находится в дескрипторе сегмента. Существует 2 дескрипторные таблицы- GDT, LDT (глобальная, локальная дескрипторные таблицы). LDT - для каждой задачи своя. Сегментные регистры используются как селекторы (индексы в таблицах дескрипторов).

Формат дескриптора сегмента: 1) базовый адрес сегмента; 2) размер сегмента (лимит).

Слово 3 (старшее):

Биты

Описание

15-8

Биты 31-24 базы

7

Бит G - гранулярности: 0-лимит в байтах;1-лимит в 4К-байтных страницах.

6

Бит разрядности (B/D):0-16-битный сегмент;1- 32-битный сегмент.

5

Равен 0

4

Зарезервировано для ОС.

3-0

Биты 19-16 лимит

Слово 2:

Биты

Описание

15

Бит присутствия (P-бит).

14-13

Уровень привилегий дескриптора (степень защиты).

12

S-бит типа дескриптора:0 - системный;1 - обычный.

11-9

Тип сегмента

8

Бит использования (A-бит).Если в течении некоторого времени сегмент не использовался, то A=0 (сегмент помещается на диск, на его место в памяти помещается другой сегмент).

7-0

Биты 23-16 базы.

Слово 1: Биты 15-0 базы.

Слово 0 (младшее): Биты 15-0 лимита.

Программа на любом языке отображается в памяти компьютера в виде отдельных кусков, называемых сегментами памяти. Сегмент - это блок адресного пространства определенного назначения. Количество сегментов памяти задается моделью памяти. Можно сказать, что модель определяет образ (карту) программы в оперативной памяти компьютера.Модель памяти задает программист. Далее ОС создает своими средствами соответствующую модель распределения памяти, т.е. формирует нужное количество программируемых сегментов в памяти РС. Линейная (Flat ) 32-битовая модель памяти Седьмая (Flat) модель памяти доступна только 32-битовым программам для Windows. В линейной модели память не сегментирована, как в других моделях. В этой модели памяти указатели и ссылки (адреса) 32-битовые. Правда это не значит, что 32-битовые программы для Windows будут выполнятся в гордом одиночестве в огромном свободном адресном пространстве. Таким программам необходимо делить память с другими процессами в операционной системе Windows. Однако линейная модель памяти позволяет создавать гигантские массивы и другие структуры данных. Следует отметить, что не возможно воспользоваться линейной моделью для программ, работающих под управлением операционной системы MS-DOS. Для программ с линейной моделью памяти нужно использовать 32-битовый автономный компилятор или его эквивалент, встроенный в среду. Результаты работы такого компилятора следует компоновать с помощью 32-битового компоновщика. Такие компиляторы и компоновщики генерируют исполняемые файлы специального переносимого формата. Файлы такого формата могут запускаться только в операционных системах Win32s, Windows 95, Windows 98, Windows NT.

  1. Win32 API и поддерживающие его платформы. Объекты ядра. Защита. Совместное использование объектов ядра несколькими процессами. Процессы. Описатель экземпляра процесса.

API содержит совокупность фукций, к которым может обращаться приложение.

Объекты ядра - это каналы, мьютексы, потоки, процессы, почтовые ящики, проекции файлов, семафоры, события, файловые объекты и др. Эти объекты создаются Win32 функциями. Каждый объект ядра на самом деле является блоком памяти, выделенный ядром и доступный только ему. Этот блок представляет собой структуру данных, в элементах которой содержится информация об объекте. Некоторые элементы (имя объекта, дескриптор защиты, счетчик числа пользователей) присутствуют во всех объектах. Почти все функции, создающие объекты ядра, принимают указатель на структуру SECURITY_ATTRIBUTES как аргумент. Большинство приложений вместо этого аргумента выдают NULL и создают объект с защитой по умолчанию. Такая защита предполагает, что администратор и создатель объекта получают к нему полный доступ, а все прочие к объекты не допускаются.

Процессы.Процесс - экземпляр выполняемой программы. В Win32 процессу отводится 4Г. В Win32 процессы, в отличие от MS DOS , инертны, они ничего не выполняют сами, но просто содержат 4Г памяти. Процесс в Windows составляют следующие компоненты:

  • Структура данных, содержащая всю инфо о процессе, в том числе список открытых дескрипторов разл-ых системных ресурсов, уникальный идентификатор процесса, различную статистическую инфо и т.д.;

  • Адресное пространство - диапазон адресов виртуальной памяти, которым может пользоваться процесс;

  • Исполняемая программа и данные, проецируемые на виртуальное адресное пространство процесса.

Также процессу принадлежат файлы, динамически выделяемая область памяти, потоки. Чтобы процесс что-нибудь выполнял , в нем необходимо создать потоки, именно они отвечают за исполнение кода, содержащегося в адресном пространстве процесса. При создании процесса создается первичный поток.

Переменные окружения.  С любым процессом связан блок переменных окружения - области памяти, выделенной в адресном пространстве процесса. Обычно дочерний процесс наследует набор переменных окружения от родительского процесса, однако родительский процесс способен управлять тем, какие переменные наследуются, какие нет.С помощью функции DWORD GetEnvironmentVariable ( LPCTSTR lpName, // указатель на имя переменной                                LPTSTR lpBuffer, // указатель на буфер, в который будет помещено значение переменной                                DWORD nSize // размер буфера в символах);

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

Создание процессов Создание Win32 процесса осуществляется вызовом одной из ф-й, как CreateProcess, CreateProcessAsUser (для Windows NT/2000) и CreateProcessWithLogonW(начиная с Windows 2000):

  • Открывается файл образа (EXE), который будет выполняться в процессе. Если исполняемый файл не является Win32 приложением, то ищется образ поддержки (support image) для запуска этой программы. Например, если исполняется файл с расширением .bat, запускается cmd.exe и т.п.

  • Создается объект ядра Win32 "процесс".

  • Создается первичный поток (стек, контекст и объект "поток").

  • Подсистема Win32 уведомляется о создании нового процесса и потока.

  • Начинается выполнение первичного потока.

  • В контексте нового процесса и потока инициализируется адресное пространство (например, загружаются требуемые DLL) и начинается выполнение программы.

Функция CreateProcess.

BOOL CreateProcess( LPCTSTR lpApplicationName, // имя исполняемого файла;

     LPTSTR lpCommandLine, // командная строка      LPSECURITY_ATTRIBUTES lpProcessAttributes,// - атрибуты защиты для объекта ядра "процесс"      LPSECURITY_ATTRIBUTES lpThreadAttributes, // атрибуты защиты для объекта ядра "поток"      BOOL bInheritHandles, // определяет, передаются ли порожденным процессам все наследуемые описатели      DWORD dwCreationFlags, // определяет флаги, влияющие на то, как именно создается новый процесс      LPVOID lpEnvironment, //обычно NULL -наследуется окружение родительского процесса      LPCTSTR lpCurrentDirectory, // текущий диск и каталог для создаваемого процесса      LPSTARTUPINFO lpStartupInfo, // указатель на структуру STARTINFO  LPPROCESS_INFORMATION lpProcessInformation );// указатель на структуру PROCESS_INFORMATION.

Завершение процесса: 1) один из потоков процесса вызывает функцию ExitProcess. 2) поток другого процесса вызывает функцию TerminateProcess. 3)все потоки процесса "умирают по своей воле", вызвав ExitTread. ОС не поддерживает процесс без первичного потока.

Когда процесс завершается, все User- и GDI-объекты, созданные процессом, уничтожаются, объекты ядра закрываются (если их не использует другой процесс), адресное пространство процесса уничтожается.

  1. Потоки. Функция CreateThread. Завершение потока. Распределение процессорного времени между потоками. Изменение класса приоритета процесса. Установка относительного приоритета потока.

Потоки. Процессы инертны. Отвечают же за исполнение кода, содержащегося в адресном пространстве процесса, потоки. Поток (thread) - некая сущность внутри процесса, получающая процессорное время для выполнения. В каждом процессе есть min 1 поток- первичный. Далее этот поток может породить другие потоки, те в свою очередь новые и т.д. Т.о., один процесс может владеть несколькими потоками, и тогда они одновременно исполняют код в адресном пространстве процесса. Каждый поток имеет:1)Уникальный идентификатор потока;2)Содержимое набора регистров процессора, отражающих состояние процессора; 3)Два стека, один из которых используется потоком при выполнении в режиме ядра, а другой - в пользовательском режиме; 4)Закрытую область памяти, называемую локальной памятью потока (thread local storage, TLS) и используемую подсистемами, run-time библиотеками и DLL.

Создание потоков. Первичный поток создается автоматически при создании процесса. Остальные потоки создаются функциями CreateThread и CreateRemoteThread (только в Win NT/2000/XP).Поток (thread) определяет последовательность выполнения кода в процессе. При инициализации процесса система создает первичный поток. Большинство приложений обходятся этим единственным первичным потоком. В более сложных приложениях потоков несколько.

HANDLE CreateThread( LPSECURITY_ATTRIBUTES lpThreadAttributes, // атрибуты защиты потока    DWORD dwStackSize, // какую часть адресного пространства поток может использовать под свой стек    LPTHREAD_START_ROUTINE lpStartAddress,// адрес ф-ии потока, с кот нач работу создаваемый поток     LPVOID lpParameter, // позволяет передавать функции потока какое-либо инициализирующее значение.     DWORD dwCreationFlags, // определяет дополнительные флаги, управляющие созданием потока     LPDWORD lpThreadId  );// адрес переменной типа DWORD,в которой функция вернет идентификатор, приписанный системой новому потоку

Завершение потока.Поток можно завершить тремя способами: 1)поток самоуничтожается вызовом функции ExitThread; 2)один из потоков данного или другого процесса вызывает функцию TerminateThread; 3)завершается процесс, содержащий данный поток.

Распределение процессорного времени между потоками. В Win95 и WinNT применяется такой алгоритм: Система выделяет процессорное время всем активным потока, исходя из их уровней приоритета, которые варьируются от 0 (низший) и до 31 (высший). Нулевой уровень присваивается в системе особому потоку обнуления страниц, обнуляющий свободные страницы при отсутствии потоков. Ни один поток, кроме него, не может иметь нулевой уровень приоритета. Когда система подключает поток к процессору, он обрабатывает потоки с одинаковым приоритетом как равноправные. Иначе говоря, на процессор передается первый поток с приоритетом 31, а по истечении его кванта времени подключается следующий поток с тем же приоритетом 31. При отсутствии потоков с приоритетом 31 система переходит к потокам с приоритетом 30.

Планирование потоков. В Windows реализована система вытесняющего планирования на основе приоритетов, в которой всегда выполняется поток с наибольшим приоритетом, готовый к выполнению. Выбранный для выполнения поток работает в течение некоторого периода, называемого квантом. Квант определяет, сколько времени будет выполняться поток, пока ОС не прервет его. По окончании кванта ОС проверяет, готов ли к выполнению другой поток с таким же (или большим) уровнем приоритета. Если таких потоков не оказалось, текущему потоку выделяется еще один квант. Однако поток может не полностью использовать свой квант. Как только другой поток с более высоким приоритетом готов к выполнению, текущий поток вытесняется, даже если его квант еще не истек.

Приоритеты. В Windows существует 32 уровня приоритета(0-31). Они группируются так: 31 - 16 уровни реального времени; 15 - 1 динамические уровни; 0 - системный уровень, зарезервированный для потока обнуления страниц (zero-page thread).Уровни приоритета присваивает сама система в 2 этапа:1) процессу присваивается опр класс приоритета. 2) потокам, принадлежащим этому процессу присваивается относит ур приоритета.При создании процесса, ему назначается один из шести классов приоритетов:Real time class (значение 24), High class (значение 13), Above normal class (значение 10), Normal class (значение 8), Below normal class (значение 6), Idle class (значение 4).

Приоритет каждого потока (базовый приоритет потока) складывается из приоритета его процесса и относительного приоритета самого потока. Есть семь относительных приоритетов потоков: Normal: такой же как и у процесса; Above normal: +1 к приоритету процесса; Below normal: -1; Highest: +2; Lowest: -2; Time critical: устанавливает базовый приоритет потока для Real time класса в 31, для остальных классов в 15. Idle: устанавливает базовый приоритет потока для Real time класса в 16, для остальных классов в 1.

Класс приоритета моно изменить BOOL_SetPriority Class(HANDLE hProcess, DWORD fdwPriority);

Относит приоритет потока в пределах одного процесса можно изменить: BOOL_SetThreadPriority(HANDLE hThread_PRIORITY_OWEST)

  1. Архитектура памяти в Win32. Виртуальное адресное пространство. Регионы в адресном пространстве. Передача региону физической памяти.

Архитектура памяти в Win32. ВWin32 виртуальное адресное пространство каждого процесса составляет 4Г. Каждому процессу отводится закрытое адресное пространство. Когда в процессе выполняется какой-либо поток, то он получает доступ только к той памяти, которая принадлежит его процессу. В разных реализациях Win32 разбиение 4-хГБайтного адресного пространства процесса на разделы осуществляется по разному.

Адресное пространство, выделяемое процессу практически все свободно (незарезервировано), поэтому, чтобы воспользоваться какой-нибудь его частью, нужно выделить в нем определенные регионы, вызвав Win32 функцию VirtualAlloc. Операция выделения региона называется резервированием (reserving). Освобождение региона осуществляется вызовом функции VirtualFree. Чтобы практически использовать зарезервированный регион адресного пространства, нужно выделить физ память и отобразить ее на этот регион. Такая операция называется передачей физической памяти. Чтобы предать физическую память региону, нужно использовать все ту же функцию VirtualAlloc.

В Win32 имеются 3 механизма управления памятью:

  1. виртуальная память для операций с большими массивами объектов;

  2. проецируемые в память файлы;

  3. кучи для работы с множеством малых объектов (динамическая память).

Для резервирования региона в адресном пространстве используется функция:

LPVOID VirtualAlloc( LPVOID lpAddress,                      DWORD dwSize,                      DWORD flAllocationType,                      DWORD flProtect  );

lpAddress - содержит адрес, указывающий, где именно система должна зарезервировать участок адресного пространства. Обычно предается NULL. dwSize - размер региона в байтах. flAllocationType - сообщает системе, что необходимо сделать: зарезервировать регион (MEM_RESERVE) или передать физическую память (MEM_COMMIT). flProtect - параметры защиты, передаваемые региону.

Память

Каждому процессу в Win32 доступно линейное 4-гигабайтное (2^32 = 4 294 967 296) виртуальное адресное пространство. Обычно верхняя половина этого пространства резервируется за операционной системой, а вторая половина доступна процессу.

Виртуальное адресное пространство процесса доступно всем потокам этого процесса. Иными словами, все потоки одного процесса выполняются в едином адресном пространстве.

С другой стороны, механизм виртуальной памяти позволяет изолировать процессы друг от друга. Потоки одного процесса не могут ссылаться на адресное пространство другого процесса.

Виртуальная память может вовсе не соответствовать структуре физической памяти. Диспетчер памяти транслирует виртуальные адреса на физические, по которым реально хранятся данные. Поскольку далеко не всякий компьютер в состоянии выделить по 4 Гбайт физической памяти на каждый процесс, используется механизм подкачки (swapping). Когда оперативной памяти не хватает, операционная система перемещает часть содержимого памяти на диск, в файл (swap file или page file), освобождая, таким образом, физическую память для других процессов. Когда поток обращается к странице виртуальной памяти, записанной на диск, диспетчер виртуальной памяти загружает эту информацию с диска обратно в память.

  1. Работа с файлами в Win32. Обзор основных функций.

1) GetLogicalDrives.Для выяснения того, какие логические диски существуют в системе, используется функцияDWORD GetLogicalDrives( VOID); Каждый установленный бит возвращаемого значения соответствует существующему в системе логическому устройству. Например, если в системе существуют диски A:, C: и D:, то возвращаемое функцией значение равно 13 (1101).

2) GetLogicalDriveStrings.

Функция DWORD GetLogicalDriveStrings( DWORD nBufferLength, LPTSTR lpszBuffer);

заполняет lpszBuffer информацией о корневом каталоге каждого логического диска в системе. Например, если в системе существуют диски A:, C: и D:, то буфер будет заполнен символами A:\<null>C:\<null>D:\<null><null>

параметр nBufferLength определяет длину буфера. Функция возвращает реальную длину буфера, необходимую для размещения всей информации. Если необходимая длина буфера заранее неизвестна, то можно воспользоваться следующим классическим приемом: DWORD dw = GetLogicalDrivesStrings( 0, NULL ) ; LPSTR lpDriveStrings = HeapAlloc( GetProcessHeap(), 0, dw*sizeof(TCHAR));

GetLogicalDrivesStrings( dw, lpDriveStrings );

3) GetDriveType. Для определения типа диска предназначена функция UINT GetDriveType( LPTSTR lpszRootPathName ); В качестве параметра ей передается символическое имя корневого каталога (напр. A:\\), а возвращаемое значение может быть одним из: DRIVE_UNKNOWN, DRIVE_NO_ROOT_DIR, DRIVE_REMOVABLE, DRIVE_FIXED, DRIVE_REMOTE, DRIVE_CDROM, DRIVE_RAMDISK.

4) GetVolumeInformation возвращает информацию о файловой системе и дисках (директориях ).

BOOL GetVolumeInformation(

LPCTSTR lpRootPathName, // имя диска(директории) [in]

LPTSTR lpVolumeNameBuffer, // название диска [out]

DWORD nVolumeNameSize, // длина буфера названия диска[in]

LPDWORD lpVolumeSerialNumber, // сериальный номер диска [out]

LPDWORD lpMaximumComponentLength, // максимальная длина файла[out]

LPDWORD lpFileSystemFlags, // опции файловой системы [out]

LPTSTR lpFileSystemNameBuffer, // имя файловой системы [out]

DWORD nFileSystemNameSize // длина буфера имени файл.сист.[in] );

5) GetDiskFreeSpaceEx. сообщает информацию о размерах сектора и кластера и о наличии свободных кластеров. BOOL GetDiskFreeSpaceEx(

LPCTSTR lpDirectoryName, // имя диска(директории) [in]

PULARGE_INTEGER lpFreeBytesAvailable,// доступно для использования(байт) [out]

PULARGE_INTEGER lpTotalNumberOfBytes, // максимальный объём( в байтах ) [out]

PULARGE_INTEGER lpTotalNumberOfFreeBytes // свободно на диске( в байтах )[out] );

6) GlobalMemoryStatus. возвращает информацию о используемой системой памяти.

VOID GlobalMemoryStatus(LPMEMORYSTATUS lpBuffer // указатель на структуру MEMORYSTATUS);

typedef struct _MEMORYSTATUS {

DWORD dwLength; // длина структуры в байтах

DWORD dwMemoryLoad; // загрузка памяти в процентах

SIZE_T dwTotalPhys; // макс. количество физической памяти в байтах

SIZE_T dwAvailPhys; // свободное количество физич. памяти в байтах

SIZE_T dwTotalPageFile; // макс. кол. памяти для программ в байтах

SIZE_T dwAvailPageFile; // свободное кол. памяти для программ в байтах

SIZE_T dwTotalVirtual; // макс. количество виртуальной памяти в байтах

SIZE_T dwAvailVirtual; // свободное количество виртуальной памяти в байтах

} MEMORYSTATUS, *LPMEMORYSTATUS; Эта функция не возвращает параметров

7) GetComputerName, GetUserNameA

Функция GetComputerName возвращает имя локального компьютера.

BOOL GetComputerName(

LPTSTR lpBuffer,//имя локал. комп.(длина буфера равна MAX_COMPUTERNAME_LENGTH+1)[out]

LPDWORD lpnSize //размер буфера (лучше поставить MAX_COMPUTERNAME_LENGTH+1) [out/in] );

Функция GetUserName возвращает имя текущего пользователя.

BOOL GetUserName(

LPTSTR lpBuffer, // имя юзера( длина буфера равна UNLEN + 1 ) [out]

LPDWORD nSize // размер буфера ( лучше поставить UNLEN + 1 ) [out/in]);

8) GetSystemDirectory, GetTempPath, GetWindowsDirectory, GetCurrentDirectory

Функция GetSystemDirectory возвращает путь к системной директории.

UINT GetSystemDirectory(

LPTSTR lpBuffer, // буфер для системной директории [out]

UINT uSize // размер буфера [in] );

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

Функция GetTempPath возвращает путь к директории, отведённой для временных файлов.

DWORD GetTempPath(

DWORD nBufferLength, // размер буфера [in]

LPTSTR lpBuffer // буфер для временной директории [out] );

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

Функция GetWindowsDirectory возвращает путь к Windows директории.

UINT GetWindowsDirectory(

LPTSTR lpBuffer, // буфер для Windows директории [out]

UINT uSize // размер буфера [in] );

Функция GetCurrentDirectory возвращает путь к текущей директории.

DWORD GetCurrentDirectory(

DWORD nBufferLength, // размер буфера [in]

LPTSTR lpBuffer // буфер для текущей директории [out] );

9) DeviceIoControl.

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

10) Для работы с каталогами и файлами предназначены функции: GetCurrentDirectory- Получение текущего каталога; SetCurrentDirectory- Смена текущего каталога; GetSystemDirectory- Получение системного каталога; GetWindowsDirectory- Получение основного каталога системы; CreateDirectory- Создание каталога; RemoveDirectory- Удаление каталога; CopyFile- Копирование файла; MoveFile- Перемещение или переименование файла; DeleteFile- Удаление файла.

11) CreateFile. HANDLE CreateFile(

LPCTSTR lpFileName, // имя файла

DWORD dwDesiredAccess, // тип доступа к файлу

DWORD dwShareMode, // режим совместного исп-я файла различными процессами

LPSECURITY_ATTRIBUTES lpSecurityAttributes, // указывает на структуру, описывающую защиту создаваемого объекта ядра. Ему может быть присвоено значение NULL

DWORD dwCreationDistribution, // определяет действия функции в зависимости от того, существует ли уже файл с указанным именем

DWORD dwFlagsAndAttributes, // определяет атрибуты файла, если он создается и задает режим работы с файлом (FILE_ATTRIBUTE_ARCHIVE, FILE_ATTRIBUTE_HIDDEN, FILE_ATTRIBUTE_NORMAL, FILE_ATTRIBUTE_READONLY, FILE_ATTRIBUTE_SYSTEM, FILE_ATTRIBUTE_TEMPORARY)

HANDLE hTemplateFile // либо равен NULL, либо задает описатель открытого файла);

В случае удачи функция CreateFile возвращает описатель открытого файла как объекта ядра. Существенно, что в противном случае она возвращает не NULL, а INVALID_HANDLE_VALUE.

Для работы с файлами используются следующие функции: ReadFile, WriteFile, SetFilePointer - Позиционирование указателя, SetEndOfFile- Изменение размера файла, FlushFileBuffers- Принудительная запись буферов кэширования на диск, LockFile, UnlockFile.

Перемещать, переименовывать, копировать или удалять папки вместе с файлами можно с помощью функции SHFileOperation.

12) FindFirstChangeNotification. Windows позволяет организовать слежение за изменениями объектов файловой системы. Для этого служит функция FindFirstChangeNotification:

HANDLE FindFirstChangeNotification(LPCTSTR lpPathName,//Путь к папке

BOOL bWatchSubtree,  // Задает необходимость слежения за изменениями во вложенных папках

  DWORD  dwNotifyFilter); // Фильтр событий

Можно продолжить слежение, используя функцию FindNextChangeNotification:

BOOL FindNextChangeNotification(HANDLE hChangeHandle).

По завершении работы идентификатор должен быть закрыт при помощи функции FindCloseChangeNotification:

BOOL FindCloseChangeNotification(HANDLE hChangeHandle).

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

  1. Файлы, проецируемые в память.

Для того, чтобы отобразить (спроецировать) файл в память, необходимо:

  1. создать или открыть файл, который необходимо спроецировать в память;

  2. создать объект ядра "проецируемый файл" mapping file;

  3. указать системе, что необходимо сделать: загрузить файл в память целиком или частично.

После того, как завершить работу с файлом, необходимо:

  1. отменить проецирование файла в память (т.е. закрыть объект);

  2. закрыть сам проецируемый файл.

Создание объекта "проецируемый файл".

HANDLE CreateFileMapping( HANDLE hFile,                          LPSECURITY_ATTRIBUTES lpFileMappingAttributes,                          DWORD flProtect,                           DWORD dwMaximumSizeHigh,                           DWORD dwMaximumSizeLow,                           LPCTSTR lpName  );

flProtect - определяет, какой атрибут защиты будет присвоен странице физической памяти, на которую проецируется файл.       PAGE_READONLY - страница только для чтения;       PAGE_READWRITE - страгица допускает как чтение, так и запись;       PAGE_WRITECOPY - при записи на страницу делается копия. Кроме того, через этот аргумент передаются и атрибуты разделов:       SEC_IMAGE - используется, когда проецируемый файл является PE-файлом;       SEC_NOCACHE - указывает на то, что данные кэшироваться не будут.

dwMaximumSizeHigh, dwMaximumSizeLow - определяет максимальный размер в байтах проецируемого файла. lpName - имя объекта "прецируемый файл";

Данная функция возвращает Handle проецируемого файла.

Проецирование данных файла на адресное пространство процесса.

Необходимо, чтобы ОС зарезервировала регион адресного пространства и передала его как физ память. LPVOID MapViewOfFile( HANDLE hFileMappingObject,                      DWORD dwDesiredAccess,                       DWORD dwFileOffsetHigh,                       DWORD dwFileOffsetLow,                      DWORD dwNumberOfBytesToMap );

dwDesiredAccess - флаги желаемого доступа (FILE_MAP_WRITE, FILE_MAP_READ и т.д.) dwFileOffsetHigh, dwFileOffsetLow - указывают системе, какой байт файла необходимо считать первым, т.е. с какого места начать отображение файла. dwNumberOfBytesToMap - количество байт файла, который необходимо спроецировать.

Отмена отображения файла:

BOOL UnmapViewOfFile( LPCVOID lpBaseAddress  );

lpBaseAddress - указатель на базовый адрес отображения файла, для которого необходимо отменить проецирование.

  1. Критические секции. Создание. Применение. Синхронизация потоков с объектами ядра. Объекты-мьютексы.

Работая параллельно, потоки совместно используют адресное пространство процесса. Также все они имеют доступ к описателям (handles) открытых в процессе объектов. Чтобы упорядочить работу потоков? Для этого используют объекты синхронизации и соответствующие механизмы.

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

  1. критических секций;

  2. семафоров;

  3. мьютексов;

  4. событий.

Критическая секция (critical section) -

  1. Это небольшой участок кода, требующий монопольного доступа к каким-то общим данным;

  2. Это средство ОС, с помощью которого происходит синхронизация потоков.

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

CRIRICAL_SECTION    g_CriticalSection; //создание объекта критической секции InitializeCriticalSection (&g_CriticalSection); //инициализация критической секции EnterCriticalSection (&g_CriticalSection);    //захват критической секции LeaveCriticalSection (&g_CriticalSection);  //выход из критической секции DeleteCriticalSection (&g_CriticalSection); //удаление объекта

Критические секции. Синхронизация в пользовательском режиме.

Критическая секция гарантирует вам, что куски кода программы, «огороженные» ею, не будут выполняться одновременно. Строго говоря, критическая секция не является объектом ядра. Она представляет собой структуру, содержащую несколько флагов и какой-то (не важно) объект ядра. При входе в критическую секцию сначала проверяются флаги, и если выясняется, что она уже занята другим потоком, то выполняется обычная wait-функция. Критическая секция примечательна тем, что для проверки, занята она или нет, программа не переходит в режим ядра (не выполняется wait-функция) а лишь проверяются флаги. Из-за этого считается, что синхронизация с помощью критических секций наиболее быстрая. Такую синхронизацию называют "синхронизация в пользовательском режиме".

Мьютесы.

Мьютексы очень похожи на критические секции, но с их помощью можно синхронизировать потоки из разных процессов. Для использования объекта мьютекс один из потоков должен создать его с помощью функции:

HANDLE CreateMutex( LPSECURITY_ATTRIBUTES lpMutexAttributes,                     BOOL bInitialOwner,                     LPCTSTR lpName  );

lpMutexAttributes - атрибуты мьютекса; bInitialOwner - определяет, должен ли поток, создавший мьютекс, быть его первоначальным владельцем (TRUE). Если приписали владельца, то мьютекс оказывается в занятом состоянии, и любой другой поток, ожидающий данный мьютекс, будет приостановлен, пока поток, создавший этот объект, не освободит его. Если bInitialOwner=FALSE, то мьютекс не принадлежит ни одному из потоков, и первый же поток из числа ожидающих этот объект может занять его и продолжить свой выполнение. lpName - имя мьютекса.

Получить описатель мьютекс можно вызовом функции:

HANDLE OpenMutex( DWORD dwDesiredAccess, // флаг доступа                   BOOL bInheritHandle, // определяет, унаследует ли дочерний процесс данный описатель                   LPCTSTR lpName // имя объекта мьютекс);

Семафоры. События.

Объекты ядра "семафор" используются для учета ресурсов. Они позволяют потоку запрашивать число доступных ресурсов. Если один или более ресурсов свободны, счетчик доступных ресурсов после после запроса уменьшается на 1.

Семафор считается свободным, если его счетчик > 0, и занятым, если счетчик = 0. При каждом вызове из потока функции WaitForSingleObject с передачей ей описателя семафора система проверяет, больше ли 0 счетчик ресурсов у данного семафора. Если да, то уменьшает счетчик на 1 и будит поток. Если счетчик семафора =0, система оставляет поток неактивным до того момента, как другой поток освободит семафор, т.е. увеличит его счетчик.

Семафоры, в отличие от мьютексов и критических секций, не передаются во владение какому-либо потоку.

Семафор создается функцией:

HANDLE CreateSemaphore( LPSECURITY_ATTRIBUTES lpSemaphoreAttributes, // указатель на атрибуты защиты                         LONG lInitialCount, // начальное значение счетчика                         LONG lMaximumCount, // максимальное значение счечика                         LPCTSTR lpName // указатель на имя объекта "семафор");

Получить описатель объекта "семафор" позволяют следующие функции:

Соседние файлы в предмете [НЕСОРТИРОВАННОЕ]