Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
LAB-1-10.doc
Скачиваний:
2
Добавлен:
01.05.2025
Размер:
747 Кб
Скачать
☆

Создание файла Test.Def. Для создания файла Test.Def необходимо выполнить следующие инструкции:

  1. Выбрать в меню File New, Text File.

  2. В окне File Name набрать имя файла Test.def.

  3. Нажать кнопку Ok.

  4. В окне файлаTest.def набрать следующий код:

; в файлах с расширением DEF ; обозначает комментарий

;DEF файл для DLL Test.dll

;

LIBRARY test

CODE PRELOAD MOVEABLE DISCARDABLE

DATA PRELOAD SINGLE

EXPORTS

;имена DLL функций

Построение файла TEST.DLL.. После создания файлов Test.cpp и Test.def нужно выбрать опцию Build в меню Build. В ответ Visual C++ создаст Test.dll.

Объявление глобальных переменных. Код, который загружает и использует TEST.Dll обращается к глобальным переменным, которые следует объявить в файле реализации диалога (TestDlg.cpp) приложения после строк:

#endif

// объявление переменной для хранения дескриптора DLL и ее //инициализация

HINSTANCE gLidTestDLL=NULL;

//объявление функций библиотеки DLL

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

Загружается библиотека DLL функцией LoadLibrary(«Test.dll»).

5.2.Требования к программе:

Написать программу, реализующую DLL модуль для явной компоновки в режимах:

  • автоматической загрузки DLL;

  • загрузки DLL с помощью управляющего элемента.

В модуле DLL реализовать две функции:

  • одна выводит текст в окно редактирования №1,

  • вторая - в окно редактирования №2.

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

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

5.3.Варианты заданий

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

  1. Динамически подключаемые библиотеки.

  2. Явная и неявная компоновка модулей DLL.

  3. Этапы создания проекта модуля DLL

  4. Написание служебного кода модуля DLL

  5. Основные файлы проекта модуля . DLL

  6. Объявление глобальных переменных функций модуля DLL в приложениях

  7. Автоматическая загрузка библиотеки DLL в приложении.

Что нужно сделать, чтобы другие пользователи могли пользоваться Вашим DLL файлом?

6. Лабораторная работа №6 Функции и свойства потоков и процессов в win32

Цель работы: изучить механизм создания потоков в Win32-разрядных приложениях.

6.1. Теоретические сведения

Многозадачность – возможность выполнять одновременно несколько задач (процессов) или запускать выполнение других процессов в фоновом режиме.

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

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

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

Существует пять основных состояний процессов (табл.6.1.).

Табл.6.1

№

Состояние

Смысл

1 .

Выполняемый

Процесс готов к выполнению

2 .

Ожидающий

Процесс ждёт выделения какого-либо ресурса

3 .

Свопированный

Процесс отсутствует в памяти

4.

ЗОМБИ

Процесс готов к уничтожению

5 .

Остановленный

Процесс приостановлен, т.е. не имеет разрешения на выполнение

.

При управлении процессами должны быть реализована ВОЗМОЖНОСТЬ:

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

  • изменения приоритета выполнения процессов;

  • текущего контроля ( анализа ) состояния процессов;

  • защиты фоновых процессов;

  • поиска « заблудших » процессов и их уничтожение (т.е. управление « ЗОМБИ» ).

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

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

Основные функции WIN32 API для работы с потоками. Функция создания потока CreateThread:

HANDLE CreateThread (

LPSECURITY_ATTRIBUTES lpThreadAttributes, // указатель на атрибуты защиты нового потока SECURITY_ATTRIBUTES;

DWORD dwStackSize,// размер стека, выделяемого потоку ; если размер равен нулю, то поток будет иметь стек такого же размера, как и породивший его поток;

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

DWORD WINAPI ThreadFunc(LPVOID lpParameter);

LPVOID lpParameter, // 32 – битный параметр (или 32-битный указатель), который передает функции потока какое-либо инициализирующее значение;

DWORD dwCreationFlags, // Если этот аргумент равен нулю, то выполнение этого потока начнется немедленно. Если этот аргумент будет равен CREATE_SUSPENDED, то начало выполнения потока будет задержано до определенных событий( например, до вызова функции ResumeThread();

LPDWORD lpThreadId // адрес идентификатора созданного потока.

); .

Если функция завершилась без ошибок, она возвращает значение вновь созданного описателя, иначе значение функции равно NULL.

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

BOOL SetThreadPriority(HANDLE hThread, int nPriority),

где hThread – описатель потока, приоритет которого изменяется,

nPriority - приоритет, который принимает одно из следующих значений:

THREAD_PRIORITY_TIME_CRITICAL // Критичный по времени

THREAD_PRIORITY_HIGHEST // Наивысший

THREAD_PRIORITY_ABOVE_NORMAL // Выше нормального

THREAD_PRIORITY_NORMAL // Нормальный

THREAD_PRIORITY_BELOW_NORMAL // Ниже нормального

THREAD_PRIORITY_LOWEST // Самый низкий

THREAD_PRIORITY_IDLE // Простаивающий

В момент создания потока начальное значение его относительного приоритета равно THREAD_PRIORITY_NORMAL.

Синхронизация потоков. В приложениях WINDOWS различают два типа потоков: потоки пользовательского интерфейса и рабочие потоки.

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

Рабочие потоки не обрабатывают сообщения WINDOWS и используются для выполнения фоновых задач.

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

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

Каждый объект может находиться в одном из двух состояний: свободном (signaled) или занятом (nonsignaled). Потоки могут останавливаться и ждать освобождения какого-либо объекта. Когда поток создан и начинает использование своего кода, сопоставленный с ним объект ядра "поток" получает статус занятого. При завершении потока соответствующий объект ядра освобождается.

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

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

Функция создания объекта мьютекса.

HANDLE CreateMutex(LPSECURITY_ATTRIBUTES lpsa,BOOL fInitiaOwner, LPTSTR lpsz MutexName).

Потоки усыпляют себя до освобождения какого-либо объекта ядра с помощью двух основных функций:

DWORD WaitForSingleObject(HANDLE hObject,DWORD dwTimeout) и

DWORD WaitForMultipleObjects(DWORD cObjects,LPHANDLE lpHandles, BOOL bWaitAll,DWORD dwTimeout).

Функция перевода объекта мьютекст в свободное состояние: ReleaseMutex(HANDLE hObject).

Отказ от объекта мьютекса происходит, когда ожидавший его поток захватывает этот объект (переводя в занятое состояние), а затем завершается.

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

Функция инициализации критической секции - InitializeCriticalSection(LPCRITICAL_SECTION lpCriticalSection).

Функция открытия критической секции – EnterCriticalSection(&g_CriticalSection).

Функция удаления критической секции – DeleteCriticalSection(&g_CriticalSection).

Функция освобождения критической секции – LeaveCriticalSection(&g_CriticalSection), где g_CriticalSection –переменная структуры CRITICAL_SECTION

Семафоры. Объекты ядра семафор (Semaphore) используются для учета ресурсов. Они позволяют потоку запрашивать число доступных ресурсов. Если один или более ресурсов свободны, счетчик доступных ресурсов после запроса уменьшается на 1.Система разрешает другому потоку запрашивать какой-либо ресурс только после уменьшения счетчиков доступных ресурсов.

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

Функция создания семафора.

HANDLE CreateSemaphore (LPSECURITY_ATTRIBUTE lpsa,

LONG cSemInitial,LONG cSemMax,LPTSTR lpszSemName).

Эта функция создаёт семафор, максимальное значение счетчика которого cSemMax. Параметр сSemInitial позволяет задать начальное состояние счетчика. Последний параметр функции lpszSemName - указатель на имя семафора. В дальнейшем это имя позволит получить описатель семафора из других процессов с помощью CreateSemaphore или OpenSemaphore.

Функция открытия семафора.

HANDLE OpenSemaphore (DWORD fdwAccess,BOOL fInherit,

LPTSTR lpszName).

Параметр fdwAccess может быть равен либо SYNCHRONIZE, либо SEMAPHORE_ALL_ACCESS. Параметр fInherit определяет, унаследует ли дочерний процесс данный описатель данного объекта. Параметр lpszName -это указатель на объект в виде строки с нулевым символом в конце.

Функция перевода семафора в свободное состояние.

BOOL ReleaseSemaphore(HANDLE hSemaphore, LONG cRelease,

LPLONG lplPrevious).

Любой поток может вызвать эту функцию когда угодно, поскольку объекты семафор не принадлежат лишь какому-то одному потоку. С её помощью счетчик ресурсов можно увеличивать более чем на 1 одновременно. Параметр cRelease определяет, как должен освобождаться семафор.

Последний параметр функции ReleaseSemaphore - lplPrevious - указатель на переменную типа LONG, в которой возвращается значение счетчика ресурсов, предшествующее тому, что получилось после его увеличения на cRelease. Если Вас не интересует это значение, передайте в параметре значение NULL.

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

Функция создания события.

HANDLE CreateEvent(LPSECURITY_ATTRIBUTES lpsa,

BOOL fManualReset, BOOL fInitialState,

LPTSTR lpszEventName),

где параметр fManualReset сообщает системе, какое событие создается : со сбросом(TRUE) или с автосбросом(FALSE); параметр fInitialState определяет начальное состояние события: свободное(TRUE) или занятое (FALSE). Функция возвращает описатель события, специфичный для конкретного процесса.

Функция открытия события.

HANDLE OpenEvent(DWORD fdwAccess, BOOL fInherit, LPTSTR lpszName).

Функция закрытия события.

CloseHandle(HANDLE hObgect), где hObgect – дискриптор объекта для закрытия.

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