Чтение онлайн

на главную - закладки

Жанры

Системное программирование в среде Windows

Харт Джонсон М.

Шрифт:

Заметьте, что дожидаться перехода в сигнальное состояние одного и того же объекта могут одновременно несколько потоков. Аналогично, функция ExitProcess переводит в сигнальное состояние как сам процесс, так и все его потоки.

Удаленные потоки

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

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

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

Понятие о потоках твердо упрочилось во многих ОС, и исторически так сложилось, что многие поставщики и пользователи UNIX предоставляли собственные частные варианты их реализации. Были разработаны некоторые библиотеки, обеспечивающие многопоточную поддержку вне ядра. В настоящее время стандартом в этой области являются потоки POSIX Pthreads. Потоки Pthreads включены в частные варианты реализации UNIX и Linux и иногда считаются частью UNIX. Соответствующие системные вызовы отличаются от обычных системных вызовов UNIX наличием в именах префикса pthread. Потоки Pthreads поддерживаются также некоторыми другими системами, отличными от UNIX, такими, например, как Open VMS.

Системный вызов pthread_create эквивалентен вызову CreateThread, a системный вызов pthread_exit — вызову ExitThread. Для организации ожидания одним потоком завершения другого применяется системный вызов pthread_join. Потоки Pthreads предоставляют очень полезную функцию pthread_cancel, гарантирующую, в отличие от функции TerminateThread, выполнение обработчиков завершения и уничтожение ненужных дескрипторов. Возможность уничтожения потоков была бы в Windows крайне желательной, но в главе 10 представлен метод, обеспечивающий получение такого же эффекта.

Использование библиотеки С впотоках

В большинстве программ требуется библиотека С, хотя бы для того, чтобы обеспечить выполнение операций над строками. Исторически так сложилось, что библиотека С была рассчитана на применение в однопоточных процессах, поэтому для хранения промежуточных результатов многие функции используют области глобальной памяти. Подобные библиотеки, в которых отсутствует многопоточная поддержка, не являются безопасными (thread-safe) с точки зрения одновременного выполнения нескольких потоков, поскольку, например, одновременно две независимые потоки могут пытаться получить доступ к библиотеке и изменить данные, содержащиеся в ее глобальной памяти. Принципы проектирования многопоточных программ будут вновь обсуждаться в главе 8, в которой описывается синхронизация объектов Windows.

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

Microsoft С решает эту проблему, предлагая реализацию библиотеки С под названием LIBCMT.LIB, которая обеспечивает многопоточную поддержку. Однако, это еще не все. Вы не должны использовать функцию CreateThread; для запуска потока и создания специфической для него области рабочей памяти

библиотеки LIBCMT.LIB необходимо пользоваться специальной функцией С, а именно, функцией _beginthreadex. Для завершения потока вместо функции ExitThread применяется функция _endthreadex.

Примечание

В качестве упрощенного варианта функции _beginthreadex предусмотрена функция _beginthread, однако использовать ее не рекомендуется. Прежде всего, функция _beginthread не имеет ни атрибутов, ни флагов защиты и не возвращает идентификатор потока. Более того, в действительности она закрывает дескриптор потока, который создает, в результате чего возвращенное значение дескриптора может оказаться недействительным на момент его сохранения родительским потоком. Не следует вызывать и функцию _endthread; она не позволяет пользоваться возвращаемым значением.

Аргументы функции _beginthreadex в точности совпадают с аргументами функций Windows, однако типы данных Windows для этой функции не определены, и поэтому тип возвращаемого значения функции _beginthread необходимо привести к типу HANDLE, что позволит избежать появления предупреждающих сообщений. Убедитесь в том, что определение символической константы _МТ предшествует любому из включаемых файлов; в примерах программ это определение содержится в файле Envirmnt.h. Больше от вас ничего не требуется. Резюмируя, перечислим действия, которые вы должны выполнить, если имеете дело со средой разработки Visual C++.

• Подключите библиотеку LIBCMT.LIB и откажитесь от использования библиотеки, заданной по умолчанию.

• Включите директиву #define _MT во все исходные файлы, в которых используется библиотека С.

• Добавьте включаемый файл <process.h>, содержащий определения функций _beginthreadex и _endthreadex.

• Создайте потоки с помощью функции _beginthreadex; не применяйте для этой цели функцию CreateThread.

• Завершите потоки посредством функции _endthreadex или просто воспользуйтесь оператором return в конце функции потока.

В приложении А вы найдете указания относительно того, как создавать многопоточные приложения. В частности, можно, и даже рекомендуется, указывать библиотеку и определять константу _МТ непосредственно в среде разработки.

Именно так будут построены все наши примеры, и функция CreateThread никогда не будет непосредственно применяться в программах даже в тех случаях, когда библиотека С в функциях потоков не используется. 

Библиотеки с многопоточной поддержкой

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

Еще один пример в главе 12 (программа 12.5) иллюстрирует альтернативный подход, в котором применяется функция DllMain и TLS, описанные далее в настоящей главе.

Пример: многопоточный поиск контекста

В программе 6.1 (grepMP) для выполнения одновременного поиска текстового шаблона в нескольких файлах использовались процессы. Программа 7.1 (grepMT), которая включает исходный код функции поиска текстового шаблона grep, обеспечивает выполнение поиска несколькими потоками в рамках одного процесса. Код функции поиска основан на вызовах функций файлового ввода/вывода библиотеки С. Основная программа аналогична той, которая предлагалась в варианте реализации, основанном на использовании процессов.

Поделиться:
Популярные книги

Камень Книга седьмая

Минин Станислав
7. Камень
Фантастика:
фэнтези
боевая фантастика
6.22
рейтинг книги
Камень Книга седьмая

Я сделаю это сама

Кальк Салма
1. Магический XVIII век
Любовные романы:
любовно-фантастические романы
5.00
рейтинг книги
Я сделаю это сама

Кровь на эполетах

Дроздов Анатолий Федорович
3. Штуцер и тесак
Фантастика:
альтернативная история
7.60
рейтинг книги
Кровь на эполетах

Сыночек в награду. Подари мне любовь

Лесневская Вероника
1. Суровые отцы
Любовные романы:
современные любовные романы
5.00
рейтинг книги
Сыночек в награду. Подари мне любовь

Кодекс Крови. Книга ХII

Борзых М.
12. РОС: Кодекс Крови
Фантастика:
боевая фантастика
попаданцы
5.00
рейтинг книги
Кодекс Крови. Книга ХII

Найди меня Шерхан

Тоцка Тала
3. Ямпольские-Демидовы
Любовные романы:
современные любовные романы
короткие любовные романы
7.70
рейтинг книги
Найди меня Шерхан

Идеальный мир для Лекаря 4

Сапфир Олег
4. Лекарь
Фантастика:
фэнтези
юмористическая фантастика
аниме
5.00
рейтинг книги
Идеальный мир для Лекаря 4

Релокант. По следам Ушедшего

Ascold Flow
3. Релокант в другой мир
Фантастика:
фэнтези
попаданцы
рпг
5.00
рейтинг книги
Релокант. По следам Ушедшего

Мир-о-творец

Ланцов Михаил Алексеевич
8. Помещик
Фантастика:
альтернативная история
5.00
рейтинг книги
Мир-о-творец

Протокол "Наследник"

Лисина Александра
1. Гибрид
Фантастика:
фэнтези
попаданцы
аниме
5.00
рейтинг книги
Протокол Наследник

Кодекс Охотника. Книга VII

Винокуров Юрий
7. Кодекс Охотника
Фантастика:
фэнтези
попаданцы
аниме
4.75
рейтинг книги
Кодекс Охотника. Книга VII

Попаданка в семье драконов

Свадьбина Любовь
Попаданка в академии драконов
Любовные романы:
любовно-фантастические романы
7.37
рейтинг книги
Попаданка в семье драконов

Новые горизонты

Лисина Александра
5. Гибрид
Фантастика:
попаданцы
технофэнтези
аниме
сказочная фантастика
фэнтези
5.00
рейтинг книги
Новые горизонты

Скрываясь в тени

Мазуров Дмитрий
2. Теневой путь
Фантастика:
боевая фантастика
7.84
рейтинг книги
Скрываясь в тени