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

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

Жанры

Основы программирования в Linux
Шрифт:

#include <pthread.h>

void *thread_function(void *arg);

char message[] = "Hello World";

int main {

 int res;

 pthread_t a_thread;

 void *thread_result;

 res = pthread_create(&a_thread, NULL, thread_function, (void *)message);

 if (res ! = 0) {

perror("Thread creation failed");

exit(EXIT_FAILURE);

 }

 printf("Waiting for thread to finish...\n");

 res = pthread_join(a_thread, &thread_result);

 if (res != 0) {

perror("Thread join-failed");

exit(EXIT_FAILURE);

 }

 printf("Thread-joined, it returned %s\n", (char *)thread_result);

 printf("Message is now %s\n", message);

 exit(EXIT_SUCCESS);

}

void *thread_function(void *arg) {

 printf("thread_function is running. Argument was %s\n", (char *)arg);

 sleep(3);

 strcpy(message, "Bye!");

 pthread_exit("Thank you for the CPU time");

}

Итак:

1. Перед

компиляцией программы вы должны убедиться в том, что определен макрос
_REENTRANT
. В некоторых системах вы также должны определить
_POSIX_C_SOURCE
, но обычно в этом нет необходимости.

2. Далее вы должны убедиться в том, что программа скомпонована с подходящей библиотекой потоков. В случае маловероятной ситуации применения старой версии дистрибутива Linux, в которой NPTL не является библиотекой потоков по умолчанию, возможно, у вас возникнет желание обновить ее, хотя большая часть программного кода, приведенного в этой главе, совместима со старой реализацией потоков в Linux. Легкий способ проверить — заглянуть в файл /usr/include/pthread.h. Если в этом файле приведен в качестве даты авторского права (copyright date) 2003 г. или более поздний, почти наверняка у вас реализация NPTL. Если указана более ранняя дата, может быть, самое время получить современную версию дистрибутива Linux.

3. Определив и установив нужные файлы, вы можете откомпилировать и скомпоновать вашу программу следующим образом:

$ cc -D_REENTRANT -I/usr/include/nptl threadl.с -о thread1 -L/usr/lib/nptl -lpthread

Примечание

Если в вашей системе по умолчанию установлена NPTL (что очень вероятно), почти наверняка вам не нужны опции

– I
и
– L
, и можно применить более простой вариант:

$ cc -D_REENTRANT thread1.с -о thread1 -lpthread

В данной главе мы будем применять этот более простой вариант строки компиляции.

4. Когда вы выполните эту программу, то увидите следующие строки:

$ ./thread1

Waiting for thread to finish...

thread_function is running. Argument was Hello World

Thread joined, it returned Thank you for the CPU time

Message is now Bye!

Стоит

потратить немного времени на анализ данной программы, поскольку мы будем использовать ее как основу в большинстве примеров этой главы.

Как это работает

Вы объявляете прототип функции, которую вызовет поток, когда вы его создадите:

void *thread_function(void *arg);

Как требует функция

pthread_create
, данная функция принимает в качестве своего единственного параметра указатель на
void
и возвращает указатель на
void
. (Мы перейдем к реализации
thread_function
через минуту.)

В функции

main
объявлено несколько переменных и затем осуществляется вызов функции
pthread_create
, чтобы начать выполнение нового потока.

pthread_t a_thread;

void *thread_result;

res = pthread_create(&a_thread, NULL, thread_function, (void *)message);

Вы передаете адрес объекта типа

pthread_t
, который можете применять в дальнейшем для ссылки на поток. Вы не хотите менять атрибуты потока, заданные по умолчанию, поэтому во втором параметре передаете
NULL
. Последние два параметра — вызываемая функция и передаваемый ей параметр.

Если вызов завершился нормально, теперь выполняются два потока. Исходный поток (

main
) продолжается и выполняет код, расположенный следом за функцией
pthread_create
, а новый поток начинает выполнение в функции, образно названной
thread_function
.

Исходный поток проверяет, запустился ли новый поток, и затем вызывает функцию

pthread_join
:

res = pthread_join(a_thread, &thread_result);

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

Новый поток начинает выполнение, запуская функцию

thread_function
, которая выводит свои аргументы, засыпает на короткий период, обновляет глобальные переменные и затем завершается, возвращая строку в поток
main
. Новый поток пишет в тот же массив
message
, к которому у исходного потока есть доступ. Если бы вы вызвали функцию
fork
вместо
pthread_create
, массив представлял бы собой копию массива
message
, а не сам массив.

Одновременное выполнение

В упражнении 12.2 показано, как написать программу, которая проверяет одновременное выполнение двух потоков. (Вы, конечно, применяете однопроцессорную систему, ЦП будет искусно переключаться между потоками, а не одновременно выполнять оба потока, используя отдельные ядра процессора аппаратными средствами.) Поскольку вы не встречались еще с какими-либо функциями синхронизации потоков, это будет очень неэффективная программа, делающая нечто, именуемое опросом (polling) двух потоков. И снова вы воспользуетесь тем, что все, за исключением локальных переменных функции, совместно используется двумя потоками в процессе.

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

На границе империй. Том 9. Часть 2

INDIGO
15. Фортуна дама переменчивая
Фантастика:
космическая фантастика
попаданцы
5.00
рейтинг книги
На границе империй. Том 9. Часть 2

Мы друг друга не выбирали

Кистяева Марина
1. Мы выбираем...
Любовные романы:
остросюжетные любовные романы
прочие любовные романы
современные любовные романы
5.00
рейтинг книги
Мы друг друга не выбирали

Гримуар темного лорда IV

Грехов Тимофей
4. Гримуар темного лорда
Фантастика:
фэнтези
боевая фантастика
попаданцы
аниме
5.00
рейтинг книги
Гримуар темного лорда IV

Старый, но крепкий

Крынов Макс
1. Культивация без насилия
Фантастика:
рпг
уся
попаданцы
5.00
рейтинг книги
Старый, но крепкий

Дважды одаренный

Тарс Элиан
1. Дважды одаренный
Фантастика:
альтернативная история
аниме
фэнтези
фантастика: прочее
попаданцы
5.00
рейтинг книги
Дважды одаренный

Александр Агренев. Трилогия

Кулаков Алексей Иванович
Александр Агренев
Фантастика:
альтернативная история
9.17
рейтинг книги
Александр Агренев. Трилогия

#Бояръ-Аниме. Газлайтер. Том 24

Володин Григорий Григорьевич
24. История Телепата
Фантастика:
боевая фантастика
попаданцы
аниме
5.00
рейтинг книги
#Бояръ-Аниме. Газлайтер. Том 24

Как я строил магическую империю 6

Зубов Константин
6. Как я строил магическую империю
Фантастика:
попаданцы
аниме
фантастика: прочее
фэнтези
5.00
рейтинг книги
Как я строил магическую империю 6

Поводырь

Щепетнов Евгений Владимирович
3. Ботаник
Фантастика:
фэнтези
6.17
рейтинг книги
Поводырь

Кадет Морозов

Шелег Дмитрий Витальевич
4. Живой лёд
Фантастика:
боевая фантастика
5.72
рейтинг книги
Кадет Морозов

Тринадцатый V

NikL
5. Видящий смерть
Фантастика:
фэнтези
попаданцы
аниме
5.00
рейтинг книги
Тринадцатый V

Я еще барон. Книга III

Дрейк Сириус
3. Дорогой барон!
Фантастика:
боевая фантастика
попаданцы
аниме
5.00
рейтинг книги
Я еще барон. Книга III

Хозяин Стужи 4

Петров Максим Николаевич
4. Злой Лед
Фантастика:
аниме
фэнтези
попаданцы
5.00
рейтинг книги
Хозяин Стужи 4

Дважды одаренный. Том II

Тарс Элиан
2. Дважды одаренный
Фантастика:
городское фэнтези
альтернативная история
аниме
5.00
рейтинг книги
Дважды одаренный. Том II