Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
Лабораторные работы СПО-new.docx
Скачиваний:
7
Добавлен:
14.11.2019
Размер:
239.58 Кб
Скачать
  • исходные тексты разработанных модулей.

    Методические указания к выполнению работы Управление процессами и потоками в ос Windows

    В ОС Windows 2000 для реализации механизма многозадачности используется два основных понятия: процесс (Process) и поток (Thread). Первый из них реализует концепцию владения ресурсами, а второй - концепцию планирования центрального процессора.

    Процесс в ОС Windows 2000 является контейнером для ресурсов и состоит из двух компонентов:

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

    • адресного пространства, в котором содержится код и данные всех EXE- и DLL модулей. Именно в нем располагаются области памяти, динамически распределяемые для стеков потоков и других нужд. Каждому процессу выделяется 4-гигабайтное адресное пространство, в котором пользователь занимает нижние 2 Гбайта, а ОС занимает остальную часть. Таким образом, ОС присутствует в адресном пространстве каждого процесса, но защищена от него с помощью аппаратного блока управления памятью MMU (Meneger Memory Unit).

    табл. 13 - Варианты индивидуальных заданий

    вар.

    Компонент VCL для управления приоритетами

    Значения базовых и относительных

    приоритетов для оценки времени

    выполнения потоков

    Название

    Страница

    палитры

    компонентов

    Изображение

    Базовые

    приоритеты

    процесса

    Относительные

    приоритеты

    потоков

    1

    TrackBar

    Win32

    BELOW_NORMAL

    NORMAL

    LOWEST

    NORMAL

    2

    ComboBox

    Standard

    NORMAL

    ABOVE_NORMAL

    NORMAL

    ABOVE_NORMAL

    3

    RadioButton

    Standard

    BELOW_NORMAL

    NORMAL

    LOWEST

    NORMAL

    4

    SpinEdit

    Samples

    ABOVE_NORMAL

    HIGH

    LOWEST

    BELOW_NORMAL

    5

    TrackBar

    Win32

    NORMAL

    ABOVE_NORMAL

    BELOW_NORMAL

    ABOVE_NORMAL

    6

    ComboBox

    Standard

    ABOVE_NORMAL

    HIGH

    BELOW_NORMAL

    NORMAL

    7

    SpinEdit

    Samples

    BELOW_NORMAL

    NORMAL

    ABOVE_NORMAL

    HIGHEST

    табл. 14 - Оценка времени выполнения процессов и потоков

    Запущенных

    процессов

    ID

    процесса

    Класс

    приоритета

    процесса

    Время

    выполнения

    процесса

    ID

    потока

    Относительный

    приоритет

    потока

    Время

    выполнения

    потока

    Кол-во

    вычислений

    1

    832

    BELOW_

    NORMAL

    1

    832

    NORMAL

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

    Создаются процессы и потоки при помощи функций Win32 API.

    Для создания процесса используется функция CreateProcess, назначение параметров которой приведено в табл. 15. При вызове данной функции система создает объект ядра "процесс", создает для нового процесса виртуальное адресное пространство, загружает в него код и данные как для исполняемого файла, так и для любых DLL (если таковые требуются). Как было указано выше этот объект - компактная структура данных, через которую операционная система управляет процессом. Далее система формирует объект ядра "поток" для первичного потока нового процесса. Как и в первом случае, объект ядра "поток" — это компактная структура данных, через которую система управляет потоком. Если системе удастся создать новый процесс и его первичный поток, CreateProcess возвращает значение TRUE. В тело созданного объекта-процесса входят следующие поля:

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

    • маркер доступа, содержащий информацию о безопасности и защите;

    • класс приоритета процесса - основа для исполнительного приоритета потоков процесса;

    • процессорная совместимость - набор процессоров, на которых могут выполняться потоки процесса;

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

    • время создания, завершения, работы процесса в режимах ядра и пользователя. Время работы процессора в режимах ядра и пользователя - это общее количество времени выполнения для всех потоков процесса.

    Подобно процессу поток реализован в форме объекта и состоит из двух компонентов:

    • объекта ядра, через который операционная система управляет потоком. Там же хранится статистическая информация о потоке;

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

    табл. 15 - Параметры функции CreateProcess

    Название параметра

    Назначение параметра

    lpApplicationName

    Указатель на имя исполняемого файла

    lpCommandLine

    Указатель на командную строку

    lpProcessAttributes

    Указатель на дескриптор защиты процесса (атрибуты доступа)

    lpThreadAttributes

    Указатель на дескриптор защиты первичного потока

    bInheritHandles

    Бит, управляющий наследованием дескрипторов

    dwCreationFlags

    Комбинация битовых флагов, определяющая способы и режимы создания процесса (способ создания, класс приоритета процесса)

    lpEnvironment

    Указатель на переменные окружения процесса

    lpCurrentDirectory

    Указатель на имя текущего рабочего каталога процесса

    lpStartupInfo

    Указатель на структуру, описывающую параметры окна на экране

    lpProcessInformation

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

    табл. 16 Параметры функции CreateThread

    Название параметра

    Назначение параметра

    lpThreadAttributes

    Указатель на дескриптор защиты

    dwStackSize

    Начальный размер стека

    lpStartAddress

    Адрес точки входа функции потока

    lpParameter

    Параметры, задаваемые пользователем

    dwCreationFlags

    Поле, задающее начальное состояние потока (готовый или блокированный)

    lpThreadId

    Указатель на идентификатор потока

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

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

    Как было сказано выше, при вызове функции CreateProcess создается процесс и его первичный поток. Если необходимо создать дополнительные потоки, нужно вызывать из первичного потока функцию CreateThread, назначение параметров которой приведено в табл. 16.

    При вызове функции CreateThread происходит следующее:

    • система создает объект ядра “поток”. Это не сам поток, а компактная структура данных, которая используется операционной системой для управления потоком и хранит статистическую информацию о потоке.

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

    • создается структура контекста для потока;

    • инициализируются регистры указателя стека и указателя команд.

    Если системе удастся создать новый поток, то функция CreateThread возвращает Handle созданного потока, в противном случае возвращается значение NULL.

    В тело созданного объекта-процесса входят следующие поля:

    • идентификатор потока;

    • контекст потока;

    • динамический приоритет - значение приоритета нити в данный момент;

    • базовый приоритет - нижний предел динамического приоритета потока;

    • процессорная совместимость потока - перечень типов процессоров, на которых может выполняться поток;

    • время создания, завершения, работы потока в режимах ядра и пользователя;

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

    • счетчик приостановок - текущее количество приостановок выполнения потока.

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

    Каждые 20мс ОС просматривает все существующие объекты ядра "поток" и отмечает те из них, которые могут получить процессорное время. Далее она выбирает один из таких объектов и загружает в регистры процессора значения из его контекста. Эта операция называется переключением контекста (context switching). По каждому потоку Windows ведет учет того, сколько раз он подключался к процессору.

    Причин, по которым осуществляется замена действующего потока другим, может быть несколько:

    • поток завершил свою работу;

    • поток исчерпал выделенный ему квант времени;

    • поток заблокирован и находится в состоянии ожидания;

    • в очереди появился поток с более высоким приоритетом.

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

    Windows 2000 поддерживает 32 уровня приоритетов, разделенных на шесть классов () реального времени, высокого, выше нормы, нормального, ниже нормы и простаивающего. Самый распространенный класс приоритета – нормальный - его использует 99% приложений.

    Класс приоритета присваивается процессу при его создании системой по умолчанию или запускающей программой. Класс приоритета процесса можно изменить, используя функцию Win32 SetPriorityClass.

    В тоже время, Windows 2000 поддерживает 7 относительных уровней приоритета потока (табл. 18): критичного ко времени, высшего, выше обычного, нормального, ниже обычного, низшего и простаивающего.

    Относительный приоритет присваивается потоку при его создании системой по умолчанию или запускающей программой. Относительный приоритет потока можно изменить, используя функцию Win32 SetThreadPriority.

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

    табл. 17 Классы приоритетов процесса

    Константа Win32

    Значение

    Описание

    IDLE_

    PRIORITY_CLASS

    0x0040

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

    BELOW_NORMAL_

    PRIORITY_CLASS

    0x4000

    Класс приоритета, промежуточный между normal и idle.

    NORMAL_

    PRIORITY_CLASS

    0x0020

    Потоки в этом процессе не предъявляют особых требований к выделению им процессорного времени.

    ABOVE_NORMAL_

    PRIORITY_CLASS

    0x8000

    Класс приоритета, промежуточный между normal и high.

    HIGH_PRIORITY_

    CLASS

    0x0080

    Потоки в этом процессе тоже должны немедленно реагировать на события, обеспечивая выполнение критических по времени задач. Этот класс присвоен, например, Task Manager, что дает возможность пользователю закрывать неконтролируемые процессы.

    REALTIME_PRIORITY_

    CLASS

    0x0100

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

    табл. 18 Относительные приоритеты потоков

    Константа Win32

    Значение

    Описание

    THREAD_PRIORITY_

    IDLE

    -15*

    Поток выполняется с приоритетом 16 в классе real-time и с приоритетом 1 в других классах.

    THREAD_PRIORITY_

    LOWEST

    -2

    Поток выполняется с приоритетом на два уровня ниже обычного для данного класса.

    THREAD_PRIORITY_

    BELOW_NORMAL

    -1

    Поток выполняется с приоритетом на один уровень ниже обычного для данного класса.

    THREAD_PRIORITY_

    NORMAL

    0

    Поток выполняется с обычным приоритетом процесса для данного класса.

    THREAD_PRIORITY_

    ABOVE_NORMAL

    1

    Поток выполняется с приоритетом на один уровень выше обычного для данного класса.

    THREAD_PRIORITY_

    HIGHEST

    2

    Поток выполняется с приоритетом на два уровня выше обычною для данного класса.

    THREAD_PRIORITY_TIME_CRITICAL

    15*

    Поток выполняется с приоритетом 31 в классе real-time и с приоритетом 15 в других классах.

    табл. 19 Исполнительные приоритеты потоков

    Относительный

    приоритет потока -

    THREAD_PRIORITY

    Класс приоритета процесса - PRIORITY_CLASS

    IDLE

    BELOW_

    NORMAL

    NORMAL

    ABOVE_

    NORMAL

    HIGH

    REALTIME

    IDLE

    1

    1

    1

    1

    1

    16

    LOWEST

    2

    4

    6

    8

    11

    22

    BELOW_NORMAL

    3

    5

    7

    9

    12

    23

    NORMAL

    4

    6

    8

    10

    13

    24

    ABOVE_NORMAL

    5

    7

    9

    11

    14

    25

    HIGHEST

    6

    8

    10

    12

    15

    26

    TIME_CRITICAL

    15

    15

    15

    15

    15

    31

    Как отмечалось выше, объекты ядра процесса и потока хранят информацию о времени создания, уничтожения, работы в режимах ядра и пользователя. Для получения этой информации используются соответственно функции Win32 API GetProcessTimes и GetThreadTimes.

    Возвращаемые параметры перечисленных функций представлены в формате FileTime, который представляет собой 64-разрядное значение – количество 100 наносекундных интервалов, прошедших с 1 января 1601 года. Такое представление неудобно для использования в программах и требует дополнительного преобразования, например, в формат SystemTime (функция FileTimeToSystemTime). Формат SystemTime представляет собой запись, состоящую из полей-значений текущего времени: года, месяца, числа месяца, дня недели, часов, минут и секунд.

    Выполнение работы

    К п.1. При помощи программы Проводник необходимо создать рабочую папку проекта в своем каталоге, например G:\DSV\SPO\3-1\MYFAMILY\LAB1, и затем запустить Delphi. После загрузки программы на экране появится оболочка среды с заготовкой приложения Windows. Затем следует сохранить проект в ранее созданной папке проекта. Для этого нужно выбрать пункт меню FileSave Project As, и в появившемся диалоговом окне установить путь к файлам модулей проекта (расширение *.pas) и основному файлу проекта (расширение *.dpr).

    После этого можно приступить к разработке приложения, внешний вид основного окна которого приведен на рис. 5.

    рис. 5 Внешний вид основного окна приложения

    К п.2. Задайте подходящее значение для свойства Caption формы Form1, а свойство BoderStyle установите в значение bsDialog (диалоговое окно). После этого разместите на форме компонент Panel1 (панель), задайте свойству Align значение alTop и удалите значение свойства Caption.

    Затем последовательно разместите на панели указанные ниже компоненты, и после размещения каждого из них задавайте свойству Align компонента значение alTop:

    • Label1 (Caption = Состояние процесса);

    • StringGrid1 (ColCount = 2, Enabled = False, FixedCols = 0, FixedRows = 0, RowCount = 4);

    • Label2 (Caption = Приоритет процесса);

    • TrackBar1 (Max = 4, Position = 2).

    Метки Label1 и Label2 отображают назначение соответственно компонентов StringGrid1 (таблица) и TrackBar1 (ползунок).

    Первый из них используется для отображения статистической текстовой информации о состоянии процесса, поэтому, для вывода названий параметров процесса в левой колонке таблицы StringGrid1 создайте обработчик события OnCreate формы TForm1, который должен содержать следующие операторы:

    procedure TForm1.FormCreate(Sender: TObject);

    begin

    StringGrid1.Cells[0,0]:='Идентификатор процесса';

    StringGrid1.Cells[0,1]:='Время создания процесса';

    StringGrid1.Cells[0,2]:='Время работы процесса';

    StringGrid1.Cells[0,3]:='Класс приоритета процесса';

    …………

    end;

    Второй компонент – ползунок – используется для задания или изменения класса приоритета процесса (). При выполнении лабораторной работы не рекомендуется использовать класс приоритета для процессов реального времени - REALTIME_PRIORITY_CLASS, поэтому TrackBar1 должен иметь пять фиксированных позиций. По умолчанию Delphi присваивает процессу класс приоритета NORMAL_PRIORITY_CLASS, поэтому первоначально ползунок должен быть установлен на второй позиции.

    Для изменения класса приоритета процесса создайте обработчик события OnChange для TrackBar1, который в зависимости от положения ползунка будет изменять класс приоритета процесса:

    procedure TForm1.TrackBar1Change(Sender: TObject);

    var ClassPriority: integer;

    begin

    case TrackBar1.Position of

    0: ClassPriority:=IDLE_PRIORITY_CLASS;

    // 1: ClassPriority:=BELOW_NORMAL_PRIORITY_CLASS;

    1: ClassPriority:=$4000;

    2: ClassPriority:=NORMAL_PRIORITY_CLASS;

    // 3: ClassPriority:=ABOVE_NORMAL_PRIORITY_CLASS;

    3: ClassPriority:=$8000;

    4: ClassPriority:=HIGH_PRIORITY_CLASS;

    end;

    SetPriorityClass(GetCurrentProcess,ClassPriority);

    end;

    В Delphi 6.0 не учтены два новых класса приоритетов процессов добавленных в Windows 2000: BELOW_NORMAL_PRIORITY_CLASS и ABOVE_NORMAL_PRIORITY_CLASS, поэтому для задания приоритета необходимо использовать конкретные значения констант. Для получения свойства Handle текущего процесса и установки его класса приоритета используются соответственно функции Win32 GetCurrentProcess и SetPriorityClass, более подробную информацию о них можно получить в разделе Windows SDK справочной системы Delphi.

    Затем разместите на текущей панели кнопку Button1 (Caption = “Закрыть”) и создайте для нее обработчик события OnClick для обеспечения возможности выхода из программы:

    procedure TForm1.Button1Click(Sender: TObject);

    begin

    Close;

    end;

    Для мониторинга текущего состояния процесса и порожденных им потоков разместите на панели компонент Timer co страницы System. Компонент Timer является невизуальным, то есть он не виден на форме во время выполнения программы. Компонент таймер работает следующим образом: через заданное число миллисекунд, которое определяется свойством Interval, генерируется событие OnTimer. В обработчике данного события нужно поместить код, который будет выполняться с заданной периодичностью. При выполнении лабораторной работы рекомендуется установить интервал таймера в 1 сек. (1000 мс).

    procedure TForm1.Timer1Timer(Sender: TObject);

    var STime: TSystemTime;

    CrTime,ExTime,KrTime,UsTime: TFileTime;

    begin

    StringGrid1.Cells[1,0]:=IntToStr(GetCurrentProcessID);

    StringGrid1.Cells[1,3]:=IntToStr(GetPriorityClass(GetCurrentProcess));

    if GetProcessTimes(GetCurrentProcess,CrTime,ExTime,KrTime,UsTime) then begin

    if FileTimeToSystemTime(CrTime,STime) then

    StringGrid1.Cells[1,1]:=DateTimeToStr(SystemTimeToDateTime(STime));

    if FileTimeToSystemTime(UsTime,STime) then

    StringGrid1.Cells[1,2]:=TimeToStr(SystemTimeToDateTime(STime));

    end;

    ……………

    end;

    Для получения идентификатора и класса приоритета процесса используются соответственно функции Win32 GetCurrentProcessID, GetPriorityClass. Для получения информации о времени создания, завершения, времени работы в режимах ядра и пользователя используется функция Win32 GetProcessTimes, которая возвращает перечисленные значения в формате времени TFileTime. Для отображения времени используется три промежуточных преобразования форматов времени:

    • TFileTime в формат TSystemTime – функция FileTimeToSystemTime;

    • TSystemTime в формат TDateTime – функция SystemTimeToDateTime;

    • TDateTime при помощи функций DateTimeToStr и TimeToStr преобразуем соответственно в строки символов времени-даты создания и времени работы процесса в пользовательском режиме

    TDateTime является внутренним форматом представления времени в Delphi. Тип TDateTime хранится в вещественной переменной типа Double, целая часть которой соответствует количеству дней, прошедших с 30 декабря 1899 года, а дробная – части текущего дня (6.00  0.25, 12.00  0.5, 18.00  0.75).

    При выполнении работы время завершения работы и время работы процесса в режиме ядра не являются информативными и поэтому не используются.

    К п.2. Для добавления потока в приложение выберите в основном меню пункт File/New/Other/Thread Object. В появившемся диалоговом окне задайте имя класса добавляемого потока, например TMyThread. После этого появится заготовка модуля соответствующего потока.

    unit Unit1;

    interface

    uses Classes;

    type

    TMyThread = class(TThread)

    private

    { Private declarations }

    protected

    procedure Execute; override;

    end;

    implementation

    procedure TMyThread.Execute;

    begin

    …………

    end;

    end.

    Класс TThread, от которого порожден поток, является объектно-ориентированной надстройкой Delphi над потоками, создаваемыми функциями Win32 API. Он освобождает пользователя от необходимости прямого использования функций Windows API для управления потоками, сохраняя при этом возможность такого управления через свойство Handle. Метод Execute должен содержать код, который будет выполняться потоком во время его работы.

    Для подсчета числа суммирований, выполняемых потоком, следует использовать целочисленную переменную Counter, для этого в описание класса TMyThread следует добавить раздел public и описать в нем поле Counter типа Integer.

    type

    TMyThread = class(TThread)

    private

    { Private declarations }

    protected

    procedure Execute; override;

    public

    Counter: Integer;

    end;

    Метод Execute, который выполняет вычисления, следует реализовать примерно следующим образом:

    procedure TMyThread.Execute;

    var i,Total: integer;

    begin

    while not Terminated do begin

    Total:=0;

    for i:=1 to 10 do Inc(Total,Random(MaxInt div 10));

    Inc(Counter);

    end;

    Поскольку обычно поток выполняет код, расположенный в методе Execute и завершает свою работу, код внутри метода следует зациклить. Для этого удобно использовать свойство Terminated потока. Свойство Terminated имеет значение True в том случае, когда по каким-то причинам следует завершить работу потока, например из основного потока приложения.

    После определения кода, который должен выполнять поток его следует сохранить в выделенной для проекта папке, предварительно определив название модуля, например Unit1. Затем подключить модуль, в котором определен поток, к проекту. Для этого в строке uses раздела interface основного модуля приложения следует написать название модуля, в котором определен поток, например:

    Uses …., Unit1;

    После этого в раздел описания переменных (var) основного модуля необходимо добавить описание двух переменных того же типа, что и поток:

    Var Thread1,Thread2: TMyThread;

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

    Вначале разместите на форме компонент Panel2 (панель), присвойте свойству Align значение alLeft и удалите значение свойства Caption.

    Затем последовательно разместите на панели указанные ниже компоненты, и после размещения каждого из них задавайте свойству Align компонента значение alTop:

    • Label3 (Caption = Состояние потока 1);

    • StringGrid2 (ColCount = 2, Enabled = False, FixedCols = 0, FixedRows = 0, RowCount = 5);

    • Label4 (Caption = Приоритет потока);

    • TrackBar1 (Max = 5, Position = 0).

    После этого на ту же панель поместите следующие компоненты:

    • CheckBox1 (Caption = Создать задержанным);

    • Button2 (Caption = Создать поток);

    • Button3 (Caption = Запустить поток);

    • Button4 (Caption = Остановить поток);

    • Button5 (Caption = Уничтожить поток);

    Метки Label3 и Label4 отображают назначение соответственно компонентов StringGrid2 и TrackBar2).

    Первый из них используется для отображения статистической текстовой информации о состоянии потока. Для вывода названий параметров потока в левой колонке таблицы StringGrid2 и обеспечения непротиворечивой работы кнопок ButtonButton5, управляющих работой потока, добавьте к ранее созданному обработчику события OnCreate формы, следующий код:

    procedure TForm1.FormCreate(Sender: TObject);

    begin

    ……………

    StringGrid2.Cells[0,0]:='Идентификатор потока

    StringGrid2.Cells[0,1]:='Время создания потока';

    StringGrid2.Cells[0,2]:='Время работы потока';

    StringGrid2.Cells[0,3]:='Количество вычислений';

    StringGrid2.Cells[0,4]:='Относительный приоритет';

    Button3.Enabled:=false;

    Button4.Enabled:=false;

    Button5.Enabled:=false;

    ……………

    end;

    Компонент TrackBar2 используется для задания или изменения относительного приоритета потока (). Delphi использует свои константы относительных приоритетов потоков, соответствие между ними и константами Win32 приведено в табл. 20.

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

    табл. 20 Относительные приоритеты потока в Delphi и Win32

    Константа Delphi

    Константа Win32

    Значение

    tpIdle

    THREAD_PRIORITY_IDLE

    -15*

    tpLowest

    THREAD_PRIORITY_LOWEST

    -2

    tpLower

    THREAD_PRIORITY_BELOW_NORMAL

    -1

    tpNormal

    THREAD_PRIORITY_NORMAL

    0

    tpHigher

    THREAD_PRIORITY_ABOVE_NORMAL

    1

    tpHighest

    THREAD_PRIORITY_HIGHEST

    2

    tpTimeCritical

    THREAD_PRIORITY_TIME_CRITICAL

    15*

    При работе приложения предполагается создание двух потоков, поэтому для избежания избыточности кода, лучше создать одну процедуру установки приоритетов - общую для обоих потоков. Для этого в разделе public класса TForm1 необходимо описать метод SetThrPrior:

    type

    TForm1 = class(TForm)

    …………

    private

    { Private declarations }

    public

    procedure SetThrPrior(Thread: TMyThread; Pos: integer);

    { Public declarations }

    end;

    А затем в разделе implementation привести его реализацию:

    procedure TForm1.SetThrPrior(Thread: TMyThread; Pos: integer);

    var Priority: TThreadPriority;

    begin

    if Thread <> nil then begin

    case Pos of

    0: Priority:=tpIdle;

    1: Priority:=tpLowest;

    2: Priority:=tpLower;

    3: Priority:=tpNormal;

    4: Priority:=tpHigher;

    5: Priority:=tpHighest;

    end; {case}

    Thread.Priority:=Priority;

    end;

    end;

    Приоритет потока определяется его свойством Priority, типа TThreadPriority. Для изменения относительного приоритета потока создайте обработчик события OnChange для TrackBar2:

    procedure TForm1.TrackBar2Change(Sender: TObject);

    begin

    SetThreadPriority(Thread1,TrackBar2.Position);

    end;

    Создание потока должно происходить при нажатии пользователем кнопки “Создать поток” (рис. 5). Для этого в обработчике OnClick соответствующей кнопки следует выполнить следующие действия:

    procedure TForm1.Button2Click(Sender: TObject);

    begin

    Thread1:=TMyThread.Create(CheckBox1.Checked);

    SetThreadPriority(Thread1,TrackBar2.Position);

    if CheckBox1.Checked then begin

    Button3.Enabled:=True;

    Button4.Enabled:=False;

    Button5.Enabled:=True;

    end else begin

    Button3.Enabled:=False;

    Button4.Enabled:=True;

    Button5.Enabled:=True;

    end;

    Button2.Enabled:=False;

    end;

    Для создания потока вызывается конструктор потока Create, определяя при этом режим создания потока (задержанный или нет). Затем задается начальный приоритет выполнения потока и обеспечивается согласованная работа кнопок при управлении потоком.

    Конструктор потока Create имеет единственный параметр CreateSuspended, который определяет, как создается поток. Если параметр CreateSuspended установлен в True, то поток создается задержанным, т.е. код, расположенный в методе Execute не выполняется до тех пор, пока поток не будет перезапущен вызовом метода Resume. В противном случае поток сразу начинает работу. Режим создания потока будет определяться пользователем при помощи соответствующего компонента CheckBox, состояние которого (отмечено или нет) в свою очередь определяется свойством Сhecked, которое имеет значение логического типа.

    Если поток создается задержанным, то его следует перезапустить, вызвав в обработчике OnСlick кнопки “Запустить поток” метод Resume:

    procedure TForm1.Button3Click(Sender: TObject);

    begin

    SetThreadPriority(Thread1,TrackBar2.Position);

    Thread1.Resume;

    Button3.Enabled:=False;

    Button4.Enabled:=True;

    end;

    Приостановить (временно) выполнение потока можно вызвав метод Suspend по нажатию кнопки “Остановить поток”. Остановка потока происходит не мгновенно, а спустя некоторое время, которое позволяет завершить код, который в данный момент времени может выполняться в методе Execute потока:

    procedure TForm1.Button4Click(Sender: TObject);

    begin

    Thread1.Suspend;

    Button3.Enabled:=True;

    Button4.Enabled:=False;

    end;

    Уничтожение потока происходит при вызове метода Terminate (для наглядности после уничтожения потока правая колонка таблицы StringGrid2 заполняется пробелами):

    procedure TForm1.Button5Click(Sender: TObject);

    var i: integer;

    begin

    Thread1.Terminate;

    Button2.Enabled:=True;

    Button3.Enabled:=False;

    Button4.Enabled:=False;

    Button5.Enabled:=False;

    for i:=0 to StringGrid2.RowCount-1 do

    StringGrid2.Cells[1,i]:='';

    end;

    При этом, для того чтобы поток снова начал работать, необходимо его заново создать.

    Для мониторинга текущего состояния потока необходимо добавить в ранее созданный обработчик события OnTimer следующий код:

    procedure TForm1.Timer1Timer(Sender: TObject);

    var STime: TSystemTime;

    CrTime,ExTime,KrTime,UsTime: TFileTime;

    begin

    ……………

    if Thread1 <> nil then

    if not Thread1.Terminated then begin

    StringGrid2.Cells[1,0]:=IntToStr(Thread1.ThreadID);

    StringGrid2.Cells[1,3]:=IntToStr(Thread1.Counter);

    StringGrid2.Cells[1,4]:=IntToStr(GetThreadPriority(Thread1.Handle));

    if GetThreadTimes(Thread1.Handle,CrTime,ExTime,KrTime,UsTime)

    then begin

    if FileTimeToSystemTime(CrTime,STime) then

    StringGrid2.Cells[1,1]:=DateTimeToStr(SystemTimeToDateTime(STime));

    if FileTimeToSystemTime(UsTime,STime) then

    StringGrid2.Cells[1,2]:=TimeToStr(SystemTimeToDateTime(STime));

    end;

    Thread1.Counter:=0;

    end;

    ……………

    end;

    Информация о номере потока (идентификаторе), который присвоен ему системой, хранится в свойстве ThreadID потока. Для получения приоритета потока используется функция Win32 GetThreadPriority. Для получения информации о времени создания, завершения, времени работы в режимах ядра и пользователя используется функция Win32 GetThreadTimes, которая возвращает перечисленные значения в формате времени TFileTime. Поэтому дальнейшие преобразования выполняются по аналогии с п.2 для процесса.

    К п.4. Повторите действия, проделанные в п.3, для обеспечения возможности работы со вторым потоком в приложении. Для этого выделите мышкой компонент Panel2, на котором расположены все компоненты управления первым потоком, щелкните правой кнопкой мышки для вызова локального меню, при появлении которого выберите пункт Edit|Copy. Теперь щелкните правой кнопкой мышки на свободном пространстве формы и в появившемся меню выберите пункт Edit|Paste. После этого необходимо присвоить свойству Align только что размещенной панели Panel3 значение alRight. Кроме этого желательно, чтобы обе панели – Panel2 и Panel3 – имели одинаковую ширину.

    Для обеспечения нормального управления вторым потоком в приложении, необходимо создать обработчики сообщений (по аналогии с п.3 для первого потока) для следующих компонентов:

    • Form1 (событие OnCreate);

    • Timer1 (OnTimer);

    • Button6÷Button9 (OnClick);

    • TrackBar3 (OnChange).

    Не забудьте согласовать текст перечисленных обработчиков в соответствии с их назначением – управление работой второго потока.

    К п.5. Для вызова Диспетчера задач Windows нажмите клавиши Ctrl+Alt+Delete и в появившемся диалоговом окне нажмите кнопку «Диспетчер задач».

    К п.6. Создайте новое приложение, разместите на форме две кнопки “Закрыть” и “Запустить процесс”. Также на форму необходимо поместить компонент OpenDilog со страницы Dilogs, который будет использоваться для определения имени файла, который следует запустить. Сохранить приложение в ту же папку, что и предыдущее.

    Процесс представляет собой приложение, которое содержит по крайней мере один поток.

    Запустить процесс можно при помощи функции WinExec Windows API. Функция WinExec описана следующим образом:

    UINT WinExec(

    LPCSTR lpCmdLine, // путь к приложению

    UINT uCmdShow // оконный стиль приложения

    );

    Таким образом, обработчик нажатия кнопки “Запустить процесс” будет иметь следующий вид:

    procedure TForm1.Button1Click(Sender: TObject);

    begin

    if OpenDialog1.Execute then

    WinExec(PChar(OpenDialog1.FileName),SW_SHOW);

    end;

    Запустить приложение, выбрать в диалоговом окне ранее созданное многопоточное приложение и запустить его.

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

    Контрольные вопросы

      1. Какой алгоритм планирования потоков используется в ОС Windows 2000 ?

      2. Какие объекты ядра используются в ОС ?

      3. Какие вы знаете классы приоритетов процесса ?

      4. Какие вы знаете относительные приоритеты потоков ?

      5. Как зависит приоритет потока от класса приоритета процесса и относительного приоритета потока ?

      6. Средства Win32 API для управления процессами и потоками.

      7. Средства Delphi для управления процессами и потоками.

      8. Как осуществить хронометраж потоков ?

      9. Чем в сущности является процесс в ОС Windows 2000 ?

      10. Какая структура создается ОС Windows 2000 при создании процесса?

      11. Чем владеет процесс в ОС Windows 2000 ?

      12. Что является единицей работы в ОС Windows 2000 процесс или поток ?

      13. Что такое контекст потока ?

      14. Какая информация хранится в контексте потока ?

    Лабораторная работа № 4

    Использование механизма сообщений для обработки событий в ОС Windows

    Продолжительность работы – 4 часа.

    Цель работы: Знакомство с обработкой событий в ОС Windows и использование механизма сообщений для обработки событий.

    Используемое оборудование: IBM – совместимый компьютер на базе процессора Pentium 166 и выше.

    Используемое программное обеспечение: Операционная система Windows 95, 98 NT, и среда программирования Delphi 4 и выше.

    Подготовка к работе

    Изучить по конспекту лекций и рекомендованной литературе:

    • организацию механизма сообщений в ОС Windows;

    • виды сообщений, передаваемых ОС окнам приложения;

    • что представляет собой сообщение и из каких частей оно состоит.

    Программа работы

      1. Определить обработчик стандартного сообщения Windows для формы из табл. 21 в соответствии с вариантом, заданным преподавателем.

    табл. 21 Варианты индивидуальных заданий

    № вар.

    Стандартное

    сообщение Windows

    Действия, выполняемые обработчиком

    сообщения

    1

    WM_LBUTTONDOWN

    Вывести в окне диалога сообщение с координатами указателя мыши

    2

    WM_LBUTTONDBLCLK

    Переместить окно в позицию, определяемую координатами указателя мыши

    3

    WM_RBUTTONUP

    Изменить тип заголовка окна свойство (BorderStyle) по выбору студента

    4

    WM_MOUSEMOVE

    Изменить случайным образом цвет окна

    5

    WM_RBUTTONDBLCLK

    Закрыть окно

    6

    WM_KEYDOWN

    Если нажата клавиша “С”, то изменить цвет окна случайным образом

    7

    WM_KEYUP

    Вывести окно сообщения с указанием нажатой клавиши

      1. Реализовать обработку этого же сообщения на уровне приложения, причём сначала разрешить обработку этого сообщения всем элементам приложения, а затем изменить обработчик сообщения таким образом, чтобы данное сообщение обрабатывала только одна из форм приложения по указанию преподавателя.

      2. Определить своё собственное сообщение в соответствии с вариантом из табл. 22, создать для него обработчик, который выполняет заданные вариантом действия при возникновении этого сообщения.

    табл. 22

    вар.

    Событие, которое

    инициирует сообщение

    Действия, выполняемые

    обработчиком сообщения

    1

    При нажатии левой кнопки мыши на форме “Новое окно”

    Изменить цвет элемента TLabel в окне “Обработка сообщений”

    2

    При закрытии окна “Новое окно”

    Переместить окно “Обработка сообщений в новую позицию на экране”

    3

    При закрытии окна “Новое окно”

    Сделать видимым компонент TLabel окна “Обработка сообщений”

    4

    При щелчке левой кнопкой мыши на кнопке “Закрыть” окна “Новое окно”

    Изменить цвет формы “Обработка сообщений’ и вид заголовка окна

    5

    При нажатии клавиши на форме “Новое окно’

    Отразить соответствующий нажатой клавише символ в компоненте TLabel окна “Обработка сообщений”

    6

    При отжатии клавиши на форме “Новое окно’

    Отразить соответствующий нажатой клавише символ в названии окна “Обработка сообщений”

    7

    При двойном щелчке мышью на форме “Новое окно”

    Спрятать окно “Обработка сообщний’

    Методические указания

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

    Сообщение Windows представляет собой запись, которая состоит из четырех полей:

    • первое поле Handle это дескриптор окна, получающего сообщение;

    • второе поле Msg (16 бит) это идентификатор (номер) сообщения, который определяет какое из событий произошло;

    • третье и четвёртое поля lParam и wParam (16 и 32 бита соответственно) содержат дополнительную информацию о сообщении.

    Например, если была нажата левая кнопка мыши, то поле Msg содержит значение WM_LBUTTONDOWN, поле wParam определяет какая кнопка мыши была нажата, а поле lParam содержит координаты указателя мыши (координата X в младших 16-ти битах, координата Y в старших 16-ти битах).

    При нажатии клавиши, поле Msg содержит значение WM_KEYDOWN, в поле wParam хранится ASCII код нажатой клавиши, а поле lParam содержит скан-код клавиши и другую информацию.

    Использование системы обозначения параметров типа lParam и wParam не удобно, поскольку необходимо постоянно помнить каким образов следует извлекать из них нужную Вам информацию. Гораздо удобнее использовать типы сообщений, предоставляемые Delphi, которые описаны в модуле Message. Так например, для всех событий мыши объявлен тип TWMMouse, описание которого напоминает следующее:

    Type TWMMouse = record

    Msg: Cardinal; {это wParam}

    Keys: Longint; {два способа определения wParam}

    Case Integer of

    0: XPos: SmalInt; {либо как координаты X и y}

    YPos: SmalInt;

    1: Pos: tSmallPoint; {или как одна точка]

    Result: LongInt; {поле результата}

    end;

    Для событий клавиатуры в модуле Message объявлен тип TWMKey

    TWMKey = record

    Msg: Cardinal; {идентификатор сообщения}

    CharCode: Word; {ASCII код нажатой клавиши}

    Unused: Word; {не используется}

    KeyData: Longint; {дополнительная информация}

    Result: Longint; {обработано ли нажатие}

    end;

    Общий синтаксис определения стандартного обработчика сообщений Windows имеет вид:

    procedure Handle_Name (var Msg: TMessageType); message WM_XXX;

    где HandlerName – имя метода; Msg – идентификатор передаваемого сообщения, TMessageType - тип записи, подходящий для данного сообщения, директива message указывает, что данный метод является обработчиком сообщения, WM_XXX - константа или выражение, которое определяет номер обрабатываемого сообщения Windows.

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

    Type

    TForm1 = class (TForm)

    private

    procedure WMRButtuonDown (var Msg: TWMMouse);

    message WM_RbuttonDown;

    .

    end; {TForm1}

    Далее в разделе implementation модуля формы следует написать код обработчика данного сообщения.

    procedure TForm1.WmrButtonDown(var Msg: TWMMouse);

    begin

    MessageDlg(‘Нажата правая кнопка мыши’,mtInformation,[mbOk],0);

    end;

    Откройте в Delphi проект, разработанный в предыдущей лабораторной работе, добавьте в основное меню приложения пункт ”Обработка сообщений”, в обработчике выбора этого пункта меню создайте новую форму проекта. Задайте название и геометрические размеры формы и определите обработчик для указанного вариантом сообщения. Запустите проект на выполнение и проверьте работоспособность обработчика сообщения, выполнив соответствующее действие.

    К п.2. Delphi предоставляет также способ обработки всех сообщений, которые получает приложение. Для этого используется свойство OnMessage объекта Application, который автоматически создаётся при запуске программы. Если определён обработчик события OnMessage, то он получает управление при любом событии, направленном в программу.

    Следующий пример приводит к появлению окна сообщения при двойном щелчке мыши на любом объекте в приложении. Обработчик события OnMessage лучше всего разместить в модуле главного окна приложения (MainF).

    type

    TForm1 = class (TForm)

    private

    procedure ProceedMessage (var Msg:TMsg; var Handled: Boolean);

    published

    procedure FormCreate (Sender : TObject);

    end; {Form1}

    ..

    implementation

    procedure TForm1.FormCreate (Sender: TObject);

    begin

    Application.OnMessage:=ProceedMessage;

    end;

    procedure TForm1.ProceedMessage (var Msg:TMsg; var Handled: Boolean);

    begin

    Handled:=False;

    If Msg.Message = WM_LBUTTONDBLCLK then

    begin

    MessageDlg(‘Двойной щелчок мыши’,mtInformation,[mbOk],0);

    Handled:=True;

    end;

    end;

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

    При создании обработчика обратите внимание, что в качестве типа – сообщения используется тип TMsg, описанный в модуле Windows:

    tagMSG = packed record

    hwnd: HWND;

    message: UINT;

    wParam: WPARAM;

    lParam: LPARAM;

    time: DWORD;

    pt: TPoint;

    end;

    TMsg = tagMSG;

    где поле hwnd определяет дескриптор окна, wParam и lParam несут информацию о подробностях события.

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

    with Msg do

    begin

    x:=lo(Msg.lParam); {извлечь координату X}

    lParam:= lParam shr 16; {сдинуть длинное слово на 16 бит вправо}

    {если объявить предварительно тип TCoord, то Y можно извлечь при помощи операции приведения типа]

    //y:=lo(TCoord(lParam).ypos);

    y:=lo(lParam); {извлечь координату Y}

    MessageDlg('Координаты '+IntTostr(x)+’:’IntToStr(y)+' ',mtInformation,[mbOk],0);

    end;

    Тип TCoord представляет собой следующее объявление:

    type tCoord = record

    xpos:word;

    ypos:word;

    end;

    Если требуется, чтобы только какое-то определенное окно приложения обрабатывало данное сообщение, следует организовать проверку на равенство дескриптора сообщения и дескриптора окна или элемента управления окна.

    Например:

    if Msg.hwnd = Form3.Handle then

    begin

    if Msg.Message = WM_KeyDown then

    .

    К п.3. Хотя Delphi предоставляет обработчики для большинства стандартных сообщений Windows, вам иногда может потребоваться создать своё собственное сообщение и определить для него соответствующий обработчик. Таким образом, чтобы обеспечить обработку собственных сообщений необходимо:

    • определить ваше собственное сообщение;

    • назначить новый обработчик этого сообщения.

    Для определения своего собственного сообщения следует задать идентификатор сообщения, который представляет собой целочисленную константу. Windows резервирует сообщения с номерами меньшими чем 1024 для своего использования. Константа WM_APP, определенная в модуле Messages, представляет собой начальный номер для всех определяемых пользователем сообщений.

    Пример определения сообщения пользователя:

    WM_MYMESSAGE = WM_APP+400;

    Если вы хотите дать информативные названия, вам следует объявить тип – запись для этого сообщения. Если вы не используете параметры сообщения или используете систему обозначения параметров (wParam, lParam и т.д.) вы можете использовать заданный по умолчанию тип сообщения TMessage.

    Идентификатор сообщения и его тип (если его необходимо создать) лучше всего определить в отдельном модуле проекта, в котором описаны все константы, используемые в проекте. Чтобы добавить в состав проекта такой модуль, выберите в основном меню Delphi FileNew… и в открывшемся окне выбрать Unit, после этого в Редакторе кода появится заготовка модуля. В разделе interface модуля следует выполнить необходимые объявления, а также подключить модуль Messages.

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

    • объявить метод в части protected раздела объявления класса;

    • метод должен быть процедурой с соответствующим названием без пробелов;

    • передать обработчику один var параметр типа сообщения – записи;

    • написать код, реализующий обработку сообщения в разделе implementation модуля;

    Пример объявления обработчика сообщения для определяемого пользователем сообщения CM_CHANGECOLOR.

    type

    TMyForm = class (TForm)

    protected

    procedure CMChangeColor (var Msg : TMessage); message CM_CHANGECOLOR;

    ..

    end; {TMyForm}

    implementation

    procedure TMyForm.CMChangeColor(var Msg: TMessage);

    begin

    Color:=Msg.lParam;

    Inherited;

    end;

    После определения обработчика сообщения следует в модуле формы, которая будет посылать сообщение в случае возникновения события, заданного вариантом, следует определить обработчик заданного события, который будет передавать сообщение форме “Обработка сообщений”, и подключить модуль в котором описан идентификатор сообщения. Для этого необходимо в Инспекторе объектов на стране Events выбрать необходимый вам обработчик события элемента, передающего сообщение о событии, щёлкнуть на нем левой кнопкой мыши и в появившейся заготовке обработчика события передать сообщение форме “Обработка сообщений”.

    Передать сообщение другой форме или элементу управления формы можно используя функции Windows API SendMessage и PostMessage.

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

    Функции SendMessage и PostMessage имеют одинаковый синтаксис, приведённый ниже:

    BOOL PostMessage(

    HWND hWnd, // дескриптор окна, которому передаётся сообщение

    UINT Msg, // передаваемое сообщение

    WPARAM wParam, // первый параметр сообщения

    LPARAM lParam // второй параметр сообщения

    );

    LRESULT SendMessage(

    HWND hWnd, // дескриптор окна, которому передаётся сообщение

    UINT Msg, // передавамое сообщение

    WPARAM wParam, // первый параметр сообщения

    LPARAM lParam // второй параметр сообщения

    );

    Пример: При щелчке левой кнопкой мыши на форме, форма передаёт сообщение другой форме, что ей необходимо изменить цвет и в lParam передаёт цвет, который следует установить.

    procedure TForm2.FormClick(Sender: TObject);

    var color:integer;

    begin

    color:=Random(10000);

    PostMessage(Form3.Handle,WM_MYMESSAGE,0,color);

    end;

    Запустите программу на выполнение, в меню откройте сначала окно, которое будет обрабатывать сообщения, затем окно, которое передаёт сообщения, выполните действия, приводящие к передаче сообщения и убедитесь, в правильности обработки сообщения.

    Контрольные вопросы

      1. В каких случаях Windows передаёт сообщения окнам?

      2. Что представляет собой сообщение и из каких частей состоит сообщение ?

      3. Kaкая информация передаётся в параметрах сообщения ?

      4. На каких уровнях можно обрабатывать сообщения в приложении ?

      5. Как определить собственное сообщение ?

      6. Как определить обработчик сообщения ?

      7. В чем разница между функциями SendMessage и PostMessage ?

    Лабораторная работа № 5

    Файловая система и файловый ввод-вывод

    Продолжительность работы – 4 часа.

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

    Используемое оборудование: любой IBM РС-совместимый компьютер.

    Используемое программное обеспечение: система программирования Delphi 6.0.

    Подготовка к работе

    Изучить по конспекту лекций, методическим указаниям к лабораторной работе и приведенной ниже литературе, следующие вопросы:

    • структура и особенности файловых систем FAT12, FAT16, FAT32, NTFS и CDFS;

    • средства Win32 API и Delphi для получения информации о логических дисках, томах и файлах;

    • средства Win32 API и Delphi для работы с логическими дисками, томами и файлами.

    Программа работы

      1. Получите у преподавателя вариант задания в соответствии с табл. 13. Запустите Delphi и создайте новый проект в отдельной рабочей папке.

      2. Разместите на форме компонент ComboBox1 для отображения информации о дисках и логических томах, присутствующих в системе. Создайте обработчик события OnCreate формы, и добавьте туда код для формирования списка о дисках и логических томах, присутствующих в системе. Запустите приложение на выполнение для проверки его работоспособности.

      3. Разместите на форме компонент, например StringGrid1, для отображения информации о выбранном в компоненте ComboBox1 диске или логическом томе. Запустите приложение на выполнение для проверки его работоспособности.

      4. Оформите отчет по лабораторной работе, который должен содержать:

  • название и цель лабораторной работы;

  • программу работы;

  • оконную форму разработанного приложения с информацией о каком-либо диске или логическом томе;