Добавил:
Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
ОС / 1.docx
Скачиваний:
185
Добавлен:
03.06.2014
Размер:
5.4 Mб
Скачать

Потоки posix (Pthreads

В качестве конкретной модели многопоточности рассмотрим потоки POSIX (напомним, что данная аббревиатура расшифровывается как Portable Operating Systems Interface of uniX kind – стандарты для переносимых ОС типа UNIX). Многопоточность в POSIX специфицирована стандартом IEEE 1003.1c, который описывает API для создания и синхронизации потоков. Отметим, что POSIX-стандарт API определяет лишь требуемое поведение библиотеки потоков. Реализация потоков оставляется на усмотрение авторов конкретной POSIX-совместимой библиотеки. POSIX-потоки распространены в ОС типа UNIX, а также поддержаны, с целью совместимости программ, во многих других ОС, например, Solaris и Windows NT.

Стандарт POSIX определяет два основных типа данных для потоков: pthread_t – дескриптор потока ; pthread_attr_t – набор атрибутов потока.

Стандарт POSIX специфицирует следующий набор функций для управления потоками:

pthread_create(): создание потока

pthread_exit():завершение потока (должна вызываться функцией потока при завершении)

pthread_cancel():отмена потока

pthread_join():заблокировать выполнение потока до прекращения другого потока, указанного в вызове функции

pthread_detach():освободить ресурсы занимаемые потоком (если поток выполняется, то освобождение ресурсов произойдёт после его завершения)

pthread_attr_init():инициализировать структуру атрибутов потока

pthread_attr_setdetachstate():указать системе, что после завершения потока она может автоматически освободить ресурсы, занимаемые потоком

pthread_attr_destroy():освободить память от структуры атрибутов потока (уничтожить дескриптор).

Имеются следующие примитивы синхронизации POSIX-потоков с помощью мьютексов (mutexes) – аналогов семафоров – и условных переменных (conditional variables) – оба эти типа объектов для синхронизации подробно рассмотрены позже в данном курсе:

- pthread_mutex_init() – создание мюьтекса;

- pthread_mutex_destroy() – уничтожение мьютекса;

- pthread_mutex_lock() – закрытие мьютекса;

- pthread_mutex_trylock() – пробное закрытие мьютекса (если он уже закрыт, вызов игнорируется, и поток не блокируется);

- pthread_mutex_unlock() – открытие мьютекса;

- pthread_cond_init() – создание условной переменной;

- pthread_cond_signal() – разблокировка условной переменной;

- pthread_cond_wait() – ожидание по условной переменной.

Рассмотрим пример использования POSIX-потоков на языке Си.

#include <stdio.h>

#include <stdlib.h>

#include <time.h>

#include <pthread.h>

static void wait_thread(void)

{

time_t start_time = time(NULL);

while (time(NULL) == start_time)

{

// никаких действий, кроме занятия процессора на время до 1 с.

}

}

static void *thread_func(void *vptr_args)

{ int i;

for (i = 0; i < 20; i++) {

fputs(" b\n", stderr);

wait_thread();

}

return NULL;

}

int main(void)

{ int i;

pthread_t thread;

if (pthread_create(&thread, NULL, thread_func, NULL) != 0) {

return EXIT_FAILURE;

}

for (i = 0; i < 20; i++) {

puts("a");

wait_thread();

}

if (pthread_join(thread, NULL) != 0) {

return EXIT_FAILURE;

}

return EXIT_SUCCESS;

}

Пример иллюстрирует параллельное выполнение основного потока, выдающего в стандартный вывод последовательность букв "a", и дочернего потока, выдающего в стандартный поток ошибок (stderr) последовательность букв "b". Обратите внимание на особенности создания потока (pthread_create), указания его тела (исполняемой процедуры потока thread_func) и ожидания завершения дочернего потока (pthread_join).

Рис. 11.2. Гистограмма периодов активности процессора.

Из схемы видно, что чем короче период активности, тем выше частота таких периодов, и наоборот, т.е. частота периодов активности обратно пропорциональна их длительности.

Потоки и процессы в Solaris (+ другие ОС)

В ОС Solaris, как уже было отмечено, используется модель потоков много / много. Кроме того, в системе используется также уже известное нам понятие облегченный процесс (lightweight process) промежуточное между концепцией пользовательского потока и системного потока. Таким образом, в ОС Solaris каждый пользовательский поток отображается в свой облегченный процесс, который, в свою очередь, отображается в поток ядра; последний может исполняться на любом процессоре (или ядре процессора) компьютерной системы. Схема организации потоков в Solaris изображена на рис. 10.5.

Рис. 10.5. Потоки в Solaris.

На рис. 10.6 изображена схема организации процесса в ОС Solaris.

Рис. 10.6. Процессы в Solaris.

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

Потоки в Windows 2000

Как уже отмечалось, в системе Windows реализована модель многопоточности "один / один". Каждый поток содержит:

идентификатор потока (thread id);

набор регистров

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

область памяти для локальных данных потока (thread-local storage – TLS).

Потоки в Linux

В системе Linux потоки называются tasks (задачами),а не threads. Поток создается системным вызовом clone(). Данный системный вызов позволяет дочерней задаче использовать общее адресное пространство с родительской задачей (процессом).

Соседние файлы в папке ОС