- •Концепция программы управляемой событиями.
- •Кодировки символов. Unicode.
- •Создание и завершение процессов.
- •Базовый приоритет процесса. Установка базового приоритета.
- •Многопоточность. Достоинства и недостатки.
- •Создание потоков.
- •Динамический приоритет потока. Установка приоритета.
- •Управление потоками: приостановка, возобновление, завершение.
- •11 Потоки и процессы как синхронизационные объекты.
- •Использование виртуальной памяти в приложениях
- •Виртуальное адресное пространство процесса
- •Как адресное пространство разбивается на разделы
- •Раздел для выявления нулевых указателей (Windows 2000 и Windows 98)
- •Раздел для совместимости с программами dos и 16-разрядной Windows (только Windows 98)
- •Раздел для кода и данных пользовательского режима (Windows 2000 и Windows 98)
- •Увеличение раздела для кода и данных пользовательского режима до 3 Гб на процессорах х86 (только Windows 2000)
- •Закрытый раздел размером 64 Кб (только Windows 2000)
- •Раздел для общих mmf (только Windows 98)
- •Раздел для кода и данных режима ядра (Windows2000 и Windows98)
- •20) Передача физической памяти страницам региона.
- •21) Проецируемые в память файлы (концепция).
- •22) Создание проекции файла
- •23) Отображение проекции в память процесса.
Создание потоков.
Каждый поток начинает выполнение с некоей входной функции. В первичном потоке таковой является main, wmain, WinMain или wWinMain. Если Вы хотите создать вторичный поток, в нем тоже должна быть входная функция, которая выглядит примерно так:
DWORD WINAPI ThreadFunc(PVOID pvParam)
{
DWORD dwResult = 0;
//...
return(dwResult);
}
Функцию потока можно назвать как угодно. Если в программе несколько функций потоков, необходимо присваивать им разные имена, иначе компилятор или компоновщик решит, что создано несколько реализации единственной функции.
Функция потока должна возвращать значение, которое будет использоваться как код завершения потока. Функции потоков должны по мере возможности обходиться своими параметрами и локальными переменными. Так как к статической или глобальной переменной могут одновременно обратиться несколько потоков, есть риск повредить ее содержимое. Однако параметры и локальные переменные создаются в стеке потока, поэтому они в гораздо меньшей степени подвержены влиянию другого потока.
Для создания дополнительных потоков, нужно вызвать из первичного потока функцию CreateThread:
HANDLE CreateThread (
1)PSECURITY_ATTRIBUTES psa;
2)DWORD cbStack;
3)PTHREAD_START_ROUTINE pfnStartAddr;
4)PVOID pvParam;
5)DWORD fdwCreate;
6)PDWORD pdwThreadID);
1) указатель на структуру SECURITY_ATTRIBUTES. Если Вы хотите, чтобы объекту ядра «поток» были присвоены атрибуты защиты по умолчанию – NULL. А чтобы дочерние процессы смогли наследовать описатель этого объекта – TRUE.
2) Этот параметр определяет, какую часть адресного пространства поток сможет использовать под свой стек.
3) адрес функции потока, с которой должен будет начать работу создаваемый поток
4) позволяет передавать функции потока какое-либо инициализирующее значение. Оно может быть или просто числовым значением, или указателем на структуру данных с дополнительной информацией.
5) дополнительные флаги, управляющие созданием потока. Он принимает одно из двух значений: 0 (исполнение потока начинается немедленно) или CREATE_SUSPENDED. В последнем случае система создает поток, инициализирует его и приостанавливает до последующих указаний. Флаг CREATE_SUSPENDED позволяет программе изменить какие-либо свойства потока перед тем, как он начнет выполнять код.
6) адрес переменной типа DWORD, в которой функция возвращает идентификатор, приписанный системой новому потоку.
Динамический приоритет потока. Установка приоритета.
Каждому потоку присваивается уровень приоритета — от 0 (самый низкий) до 31 (самый высокий). Решая, какому потоку выделить процессорное время, система сначала рассматривает только потоки с приоритетом 31 и подключает их к процессору по принципу карусели. Если поток с приоритетом 31 не исключен из планирования, он немедленно получает квант времени, по истечении которого система проверяет, есть ли еще один такой поток. Если да, он тоже получает свой квант процессорного времени.
Пока в системе имеются планируемые потоки с приоритетом 31, ни один поток с более низким приоритетом процессорного времени не получает. Такая ситуация называется "голоданием* (starvation). Она наблюдается, когда потоки с более высоким приоритетом так интенсивно используют процессорное время, что остальные практически не работают.
При загрузке системы создается особый поток — поток обнуления страниц (zero page thread), которому присваивается нулевой уровень приоритета. Ни один поток, кроме этого, не может иметь нулевой уровень приоритета Он обнуляет свободные страницы в оперативной памяти при отсутствии других потоков, требующих внимания со стороны системы.
Windows поддерживает семь относительных приоритетов потоков
Относительный приоритет потока |
Описание
|
Time-critical (критичный по времени) |
Поток выполняется с приоритетом 31 в классе real-time и с приоритетом 15 в других классах |
Highest (высший) |
Поток выполняется с приоритетом на два уровня выше обычною для данного класса |
Above normal (выше обычного) |
Поток выполняется с приоритетом на один уровень выше обычного для данного класса |
Normal (обычный) |
Поток выполняется с обычным приоритетом процесса для данного класса |
Below normal (ниже обычного) |
Поток выполняется с приоритетом на один уровень ниже обычного для данного класса |
Lowеst (низший) |
Поток выполняется с приоритетом на два уровня ниже обычного для данного класса |
Idle (простаивающий) |
Поток выполняется с приоритетом 16 в классе real-time и с приоритетом 1 в других классах |
Относительный приоритет потока |
Idle |
Класс приоритета процесса |
Real-lime |
|||
Below normal |
Normal |
Above normal |
Highest |
|||
Time-critical |
15 |
15 |
15 |
15 |
15 |
31
|
Highest |
6 |
8 |
10 |
12 |
15 |
26 |
Above normal |
5 |
7 |
9 |
11 |
14 |
25 |
Normal |
4 |
6 |
8 |
10 |
13 |
24 |
Below normal |
3 |
5 |
7 |
9 |
12 |
23 |
Lowеst |
2 |
4 |
6 |
8 |
11 |
22 |
Idle |
1 |
1 |
1 |
1 |
1 |
16 |
Только что созданный поток получает относительный приоритет normal.
BOOL SetThreadPriority( HANDLE hThread, int nPriority);
Разумеется, параметр bThread указывает на поток, чей приоритет Вы хотите из менить, а через nPriority передается один из идентификаторов
Относительный приоритет потока |
Идентификатор |
Time-critical |
THREAD_PRIORITY_TIME_CRITICAL |
Highest |
THREAD_PRIORITY_HIGHEST |
Above normal |
THREAD_PRIORITY_ABOVE_NORMAL |
Normal |
THREAD_PRIORITY_NORMAL |
Below normal |
THREAD_PRIORITY_BELOW_NORMAL |
Lowest |
THREAD_PRIORITY_LOWEST |
Idle |
THREAD_PRIORITY_IDLE |
Функция GetThreadPnority, парная SetThreadPriority, позволяет узнать относительный приоритет потока.
int GetThreadPriority(HANDLE hThread);
Она возвращает один из идентификаторов, показанных в таблице выше.