The website "dmilvdv.narod.ru." is not registered with uCoz.
If you are absolutely sure your website must be here,
please contact our Support Team.
If you were searching for something on the Internet and ended up here, try again:

About uCoz web-service

Community

Legal information

6.3.1 Создание потока и выход из него

6.3.1 Создание потока и выход из него

Предыдущая  Содержание  Следующая V*D*V

Новый поток выполнения создается вызовом функции pthread_create. Прототип функции:

 

int pthread_create (pthread_t * thread_id,

                    pthread_attr_t *thread_attributes,

                    void * (*start_routine)(void *),

                    void * arg);

 

Функция возвращает ноль в случае успеха, а идентификатор созданного потока хранится в первом аргументе, thread_id. Новый поток начинает свое выполнение с функции start_routine. arg является аргументом start_routine. thread_attributes представляет собой различные атрибуты потока, такие как политика планирования, приоритет, размер стека, и тому подобное. В случае неудачи функция возвращает ненулевое значение.

Давайте обратимся к нашему MP3-плееру в player.c. При запуске плеера для инициализации всех подсистем вызывается функция system_init. Функция system_init выполняется в контексте основного потока.

 

int system_init(){

  pthread_t audio_tid;

  int sample = 1;

  void * audio_init_status;

  /* Инициализируем звуковую подсистему в отдельном потоке */

  if (pthread_create(&audio_tid, NULL, audio_init,

                        (void *)sample) != 0){

    printf("Audio thread creation failed.\n");

    return FAIL;

  }

  /*

   * Инициализируем остальное приложение, структуры данных и т.д.

   */

 

  ....

  ....

}

 

Чтобы осуществить инициализацию звуковой подсистемы в новом потоке, system_init вызывает pthread_create. В случае успеха идентификатор потока созданного потока сохраняется в audio_tid. Новый поток выполняет функцию audio_init. audio_init принимает целочисленный аргумент sample. Вторым аргументом pthread_create является NULL, поток audio_tid начинает работать со стандартным набором атрибутов. (Например, политика планирования и приоритет потока наследуются от вызывающего.)

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

 

void* audio_init(void *sample){

  int init_status = SUCCESS;

  printf("Audio init thread created with ID %d\n",

                                  pthread_self());

  /*

   * Инициализируем подсистему MP3 декодера.

   * При неудаче устанавливаем init_status = FAIL.

   */

  /*

   * Инициализируем подсистему вывода звука.

   * При неудаче устанавливаем init_status = FAIL.

   */

 

  if ((int)sample){

 

  /*

   * Проигрываем звук в течение 2-х секунд.

   * При неудаче при воспроизведении

   * устанавливаем init_status = FAIL.

   */

 }

  printf("Audio subsystem initialized\n");

 

  pthread_exit((void *)init_status);

}

 

Возникают два вопроса:

 

Как поток audio_init может отправить своё выходное состояние в основной поток?

Может ли функция system_init подождать окончания потока audio_init перед выходом? Как можно передать выходное  состояние потока audio_init?

 

Поток устанавливает своё выходное состояние используя функцию pthread_exit. Эта функция также завершает выполнение вызывающего потока.

 

void pthread_exit(void *return_val);

 

audio_init вызывает pthread_exit, чтобы прекратить его выполнение, а также установить его состояние завершения. pthread_exit аналогичен системному вызову exit. С точки зрения разработчика приложения есть только одна разница: exit завершает весь процесс, а pthread_exit прекращает только вызывающий поток.

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

 

int pthread_join(pthread_t tid, void **thread_return_val);

 

pthread_join приостанавливает выполнение вызывающего потока до завершения потока tid. Когда pthread_join возвращается, выходное состояние потока tid сохраняется в аргументе thread_return_val. pthread_join аналогичен системному вызову wait4. wait4 приостанавливает выполнение родительского процесса до тех пор, пока потомок, указанный в его аргументе, не завершится. Аналогично, pthread_join также приостанавливает выполнение вызывающего потока, пока поток, указанный в его аргументе, не завершится. Как вы можете видеть, system_init вызывает pthread_join, чтобы дождаться перед выходом завершения потока audio_init. Она также печатает сообщение об ошибке, если audio_init заканчивается неудачей.

 

int system_init(){

    ...

  void * audio_init_status;

    ...

    ...

  /* Ожидаем завершения потока audio_init */

  pthread_join(audio_tid, &audio_init_status);

 

  /* Если инициализация звука не удалась, возвращаем ошибку */

  if ((int)audio_init_status == FAIL){

    printf("Audio init failed.\n");

    return FAIL;

  }

 

  return SUCCESS;

}

 

Обратите внимание, что поток, создаваемый с помощью pthread_create со стандартным набором атрибутов (вторым аргументом pthread_create является NULL), является потоком, допускающим объединение. Ресурсы, выделяемые на объединяемые потоки, не освобождаются, пока какой-нибудь другой поток вызывает pthread_join для такого потока. Он становится зомби.

 

Предыдущая  Содержание  Следующая