Скачиваний:
90
Добавлен:
12.05.2015
Размер:
913.92 Кб
Скачать

Функции управления процессами и потоками

Процессы

Потоки

Описание действий для потоков

fork

pthread_create

Создать новый поток управления

exit

pthread_exit

Завершить существующий поток управления

waitpid

pthread_join

Вернуть код завершения потока управления

atexit

pthread_cleanup_push

Зарегистрировать функцию обработки выхода из потока управления

getpid

pthread_self

Вернуть идентификатор потока управления

abort

pthread_cancel

Запросить принудительное завершение потока управления

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

#include <pthread.h>

int pthread_detach (pthread_t tid);

/* функция возвращает 0 в случае успеха, код ошибки – в случае неудачи */

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

14.6. Установка атрибутов потока

Во всех примерах главы 14, где мы вызывали функцию pthread_create, мы передавали ей значение NULL вместо указателя на структуру pthread_attr_t. Структура pthread_attr_t используется для того, чтобы изменить значения атрибутов по умолчанию и связать эти атрибуты с создаваемым потоком. Для инициализации структуры pthread_attr_t можно обратиться к функции pthread_attr_init. После вызова этой функции структура pthread_attr_t будет заполнена значениями атрибутов по умолчанию, которые поддерживает данная реализация Unix. Для изменения отдельных атрибутов необходимо обратиться к помощи других функций, которые будут описаны в этом разделе. Для разрушения структуры pthread_attr_t используется функция pthread_attr_destroy.

#include <pthread.h>

int pthread_attr_init (pthread_attr_t *attr);

int pthread_attr_destroy (pthread_attr_t *attr);

/* обе функции возвращают 0 в случае успеха, код ошибки – в случае неудачи */

Если функция pthread_attr_init реализована таким образом, что она размещает какие-либо данные в динамически выделенной области памяти, то функция pthread_attr_destroy освободит ее. Кроме того, функция pthread_attr_destroy заполнит структуру ошибочными значениями, чтобы функция pthread_create возвращала ошибку при случайном использовании такой структуры.

Структура pthread_attr_t непрозрачна для приложения. Это означает, что приложение ничего не должно знать о внутреннем содержимом структуры, что способствует повышению переносимости приложений. Следуя этому соглашению, стандарт Posix.1 определяет по две отдельные функции для получения и изменения значений каждого атрибута. Здесь мы упомянем только один атрибут – атрибут обособленности потока (detachstate).

В разделе 14.5 мы уже использовали понятие “обособленный поток”. Если нас не интересует код завершения существующего потока, мы можем обратиться к функции pthread_detach, чтобы позволить операционной системе утилизировать ресурсы, занятые потоком, после его завершения.

Если заранее известно, что код завершения потока не потребуется, то можно сразу же создать и запустить поток в обособленном состоянии, изменив значение атрибута detachstate в структуре pthread_attr_t. Для этой цели предусмотрена функция pthread_attr_setdetachstate, которой передается одно из двух возможных значений – PTHREAD_CREATE_DETACHED, чтобы запустить поток в обособленном состоянии, или PTHREAD_CREATE_JOINABLE, чтобы запустить поток в нормальном состоянии, в котором приложение сможет получить код завершения потока.

#include <pthread.h>

int pthread_attr_getdetachstate (pthread_attr_t *attr, int *detachstate);

int pthread_attr_setdetachstate (pthread_attr_t *attr, int detachstate);

/* обе функции возвращают 0 в случае успеха, код ошибки – в случае неудачи */

Чтобы получить текущее состояние атрибута detachstate, следует использовать функцию pthread_attr_getdetachstate. По адресу, который передается во втором аргументе, функция запишет одно из двух возможных значений: PTHREAD_CREATE_DETACHED или PTHREAD_CREATE_JOINABLE, в зависимости от значения указанного атрибута в структуре pthread_attr_t.

Пример. В листинге 12.1 приведена функция, которую можно использовать для создания потока в обособленном состоянии.

Листинг 12.1. Создание потока в обособленном состоянии

int makethread(void *(*fn)(void *), void *arg)

{

int err;

pthread_t tid;

pthread_attr_t attr;

err = pthread_attr_init(&attr);

if (err != 0)

return(err);

err = pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);

if (err == 0)

err = pthread_create(&tid, &attr, fn, arg);

pthread_attr_destroy(&attr);

return(err);

}

Обратите внимание, что мы игнорируем значение, возвращаемое функцией pthread_attr_destroy. В данном случае мы корректно инициализировали атрибуты потока, поэтому вызов функции pthread_attr_destroy должен быть удачным. Тем не менее, если бы вызов этой функции завершился неудачно, то восстановление после такой ошибки было бы достаточно сложным: мы должны были бы разрушить только что созданный поток, который, возможно, уже работает асинхронно по отношению к этой функции. Самое худшее, что может случиться в случае игнорирования значения, возвращаемого функцией pthread_attr_destroy, – это утечка небольшого объема памяти, который, возможно, был распределен функцией pthread_attr_init. Но в любом случае, если вызов функции pthread_attr_init успешен, а pthread_attr_destroy – неудачен, у нас все равно нет никакой стратегии восстановления после такой ошибки, потому что содержимое структуры с атрибутами потока непрозрачно для приложения. Для освобождения памяти, занимаемой структурой pthread_attr_t, определена одна-единственная функция pthread_attr_destroy, и ее вызов завершился неудачно.

Соседние файлы в папке Chapter.4