Знакомство с функциями ОС Linux, относящимися к работе с потоками, страница 2

Функция pthread_cancel посылает запрос завершения потоку thread. Если такого потока нет, то pthread_cancel завершается с ошибкой. В противном случае она возвращает ноль. Запрос завершения информирует поток thread, чтобы он завершился как можно быстрее. Однако выдача этого запроса вовсе не гарантирует того, что поток получит или обработает этот запрос. Например, если запрос завершения появляется во время очень важной операции, поток продолжит свою работу (в случае, если то, что делает поток не может быть прервано в той точке, где происходит запрос).

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

Существует несколько способов завершения потоков в ОС Linux:

Поток возвращается из своей функции (главной функции для потока). По умолчанию библиотека Pthreads забирает все ресурсы, использованные этим потоком; это подобно завершению процесса, когда управление достигает конца функции main.

Поток вызывает функцию pthread_exit.

Поток завершается через запрос завершения из другого потока, использующего для этого функцию pthread_cancel.

Поток получает сигнал, который его завершает.

Весь процесс завершает свое выполнение по системному вызову exec или exit.

Атрибуты потоков

Потоки имеют много атрибутов, которые могут быть установлены во время создания.

Установка атрибутов выполняется заполнением объекта типа pthread_attr_t и передачу его в качестве второго аргумента функции pthread_create. Передача NULL эквивалентна передаче атрибутов по умолчанию. Одни и те же атрибуты могут быть использованы для создания нескольких потоков.

Идентификация потоков

pthread_t pthread_self(void);

Возвращает уникальный идентификатор вызывающего потока.

int pthread_equal(pthread_t thread1, pthread_t thread2);

Сравнивает два идентификатора: если два идентификатора различны, то возвращаемое значение – ноль, иначе – ненулевое значение. Оператор «==» не может быть использован для сравнения двух идентификаторов потоков.

Примеры использования библиотеки потоков

Пример 1. Создание и уничтожение потока

#include <stdio.h>

#include <pthread.h>

void *kidfunc(void *p)

{ printf ("Kid ID is ---> %d\n", getpid( )); }

main ( )

{

pthread_t kid ;

pthread_create (&kid, NULL, kidfunc, NULL) ;

printf ("Parent ID is ---> %d\n", getpid( )) ;

pthread_join (kid, NULL) ;

printf ("No more kid!\n") ;

}

Результат работы программы:

[nus@localhost code]$ gcc lab6_1.c -o lab6_1.exe -lpthread

[nus@localhost code]$ lab6_1.exe

Parent ID is ---> 2577

Kid ID is ---> 2579

No more kid!

Пример 2. Разделение глобальных данных между потоками

#include <stdio.h>

#include <pthread.h>

int glob_data = 25 ;

void *kidfunc(void *p)

{

printf ("Kid here. Global data was %d.\n", glob_data) ;

glob_data = 12 ;

printf ("Kid Again. Global data was now %d.\n", glob_data) ;

}

main ( )

{

pthread_t kid ;

pthread_create (&kid, NULL, kidfunc, NULL) ;

printf ("Parent here. Global data = %d\n", glob_data) ;

glob_data = 33 ;

pthread_join (kid, NULL) ;

printf ("End of program. Global data = %d\n", glob_data) ;

}

Результат работы программы:

Kid here. Global data was 25.

Kid Again. Global data was now 12.

Parent here. Global data = 12

End of program. Global data = 33

Пример 3. Множественные потоки

#include <pthread.h>

#include <stdio.h>

#define NUM_THREADS 5

void *PrintHello(void *threadid)

{

printf("I'm thread number %d.\n", threadid);

pthread_exit(NULL);

}

int main( )

{

pthread_t threads [NUM_THREADS];

int rc, t;

for(t=0; t < NUM_THREADS; t++) {

printf ("Creating thread %d\n", t);

rc = pthread_create (&threads[t], NULL, PrintHello, (void *) t );

if (rc) {

printf("ERROR; return code from pthread_create() is %d\n", rc);

exit(-1);

}

}

pthread_exit(NULL);

}

Результат работы программы:

Creating thread 0

I'm thread number 0.

Creating thread 1

I'm thread number 1.

Creating thread 2

I'm thread number 2.

Creating thread 3

I'm thread number 3.

Creating thread 4

I'm thread number 4.

Пример 4. Разница между процессом и потоком

#include <stdio.h>

#include <pthread.h>

#include <unistd.h>

int this_is_global;

void thread_func(void *dummy) {

int local_thread;

printf("Thread %d, pid %d, addresses: &global: 0x%X, &local: 0x%X\n",

pthread_self(),getpid(),&this_is_global, &local_thread);

this_is_global++;

printf("In Thread %d, incremented this_is_global=%d\n", pthread_self(),

this_is_global);

pthread_exit(0);

}

int main( )

{

int local_main;

int pid, status;

pthread_t thread1, thread2;

printf("First, we create two threads to see better what context they