MyBooks.club
Все категории

Марк Митчелл - Программирование для Linux. Профессиональный подход

На сайте mybooks.club вы можете бесплатно читать книги онлайн без регистрации, включая Марк Митчелл - Программирование для Linux. Профессиональный подход. Жанр: Программирование издательство -,. Доступна полная версия книги с кратким содержанием для предварительного ознакомления, аннотацией (предисловием), рецензиями от других читателей и их экспертным мнением.
Кроме того, на сайте mybooks.club вы найдете множество новинок, которые стоит прочитать.

Название:
Программирование для Linux. Профессиональный подход
Издательство:
-
ISBN:
-
Год:
-
Дата добавления:
17 сентябрь 2019
Количество просмотров:
293
Читать онлайн
Марк Митчелл - Программирование для Linux. Профессиональный подход

Марк Митчелл - Программирование для Linux. Профессиональный подход краткое содержание

Марк Митчелл - Программирование для Linux. Профессиональный подход - описание и краткое содержание, автор Марк Митчелл, читайте бесплатно онлайн на сайте электронной библиотеки mybooks.club
Данная книга в основном посвящена программированию в среде GNU/Linux. Авторы применяют обучающий подход, последовательно излагая самые важные концепции и методики использования расширенных возможностей системы GNU/Linux в прикладных программах. Читатели научатся писать программы, к интерфейсу которых привыкли пользователи Linux; освоят такие технологии, как многозадачность, многопотоковое программирование, межзадачное взаимодействие и взаимодействие с аппаратными устройствами; смогут улучшить свои программы, сделав их быстрее, надежнее и безопаснее; поймут особенности системы GNU/Linux, ее ограничения, дополнительные возможности и специфические соглашения.Книга предназначена для программистов, уже знакомых с языком С и имеющих базовый опыт работы в GNU/Linux.

Программирование для Linux. Профессиональный подход читать онлайн бесплатно

Программирование для Linux. Профессиональный подход - читать книгу онлайн бесплатно, автор Марк Митчелл

С концептуальной точки зрения поток существует внутри процесса, являясь более мелкой единицей управления программой. При вызове программы Linux создает для нее новый процесс, а в нем — единственный поток, последовательно выполняющий программный код. Этот поток может создавать дополнительные потоки. Все они находятся в одном процессе, выполняя ту же самую программу, но, возможно, в разных ее местах.

Мы уже знаем, как программа порождает дочерний процесс. Первоначально он находится в родительской программе, получая копии ее виртуальной памяти, дескрипторов файлов и т.п. Модификация содержимого памяти, закрытие файлов и другие подобные действия в дочернем процессе не влияют на работу родительского процесса и наоборот. С другой стороны, когда программа создает поток, ничего не копируется. Оба потока — старый и новый — имеют доступ к общему виртуальному пространству, общим дескрипторам файлов и другим системным ресурсам. Если, к примеру, один поток меняет значение переменной, это изменение отражается на другом потоке. Точно так же, когда один поток закрывает файл, второй поток теряет возможность работать с этим файлом. В связи с тем что процесс и все его потоки могут выполнять лишь одну программу одновременно, как только одни из потоков вызывает функцию семейства exec(), все остальные потоки завершаются (естественно, новая программа может создавать собственные потоки).

В Linux реализована библиотека API-функций работы с потоками, соответствующая стандарту POSIX (она называется Pthreads). Все функции и типы данных библиотеки объявлены в файле <pthread.h>. Эти функции не входят в стандартную библиотеку языка С, поэтому при компоновке программы нужно указывать опцию -lpthread в командной строке.

4.1. Создание потока

Каждому потоку в процессе назначается собственный идентификатор. При ссылке на идентификаторы потоков в программах, написанных на языке С или C++, нужно использовать тип данных pthread_t.

После создания поток начинает выполнять потоковую функцию. Это самая обычная функция, которая содержит код потока. По завершении функции поток уничтожается. В Linux потоковые функции принимают единственный параметр типа void* и возвращают значение аналогичного типа. Этот параметр называется аргументом потока. Через него программы могут передавать данные потокам. Аналогичным образом через возвращаемое значение программы принимают данные от потоков.

Функция pthread_create() создает новый поток. Ей передаются следующие параметры.

■ Указатель на переменную типа pthread_t, в которой сохраняется идентификатор нового потока.

■ Указатель на объект атрибутов потока. Этот объект определяет взаимодействие потока с остальной частью программы. Если задать его равным NULL, поток будет создан со стандартными атрибутами. Подробнее данная тема обсуждается в разделе 4.1.5, "Атрибуты потоков".

■ Указатель на потоковую функцию. Функция имеет следующий тип:

void* (*)(void*)

■ Значение аргумента потока (тип void*). Данное значение без каких-либо изменений передается потоковой функции.

Функция pthread_create() немедленно завершается, и родительский поток переходит к выполнению инструкции, следующей после вызова функции. Тем временем новый поток начинает выполнять потоковую функцию. ОС Linux планирует работу обоих потоков асинхронно, поэтому программа не должна рассчитывать на какую-то согласованность между ними.

Программа, представленная в листинге 4.1, создает поток, который непрерывно записывает символы 'x' в стандартный поток ошибок. После вызова функции pthread_create() основной поток начинает делать то же самое, но вместо символов 'x' печатаются символы 'o'.

Листинг 4.1. (thread-create.c) Создание потока

#include <pthread.h>

#include <stdio.h>


/* Запись символов 'x' в поток stderr.

   Параметр не используется.

   Функция никогда не завершается. */


void* print_xs(void* unseed) {

 while (1)

  fputc('x', stderr);

 return NULL;

}


/* Основная программа. */

int main() {

 pthread_t thread_id;

 /* Создание потока. Новый поток выполняет

    функцию print_xs(). */

 pthread_create(&thread_id, NULL, &print_xs, NULL);

 /* Непрерывная запись символов 'o' в поток stderr. */

 while (1)

  fputc('o', stderr);

 return 0;

}

Компиляция и компоновка программы осуществляются следующим образом:

% cc -o thread-create thread-create.c -lpthread

Запустите программу, и вы увидите, что символы 'x' и 'o' чередуются самым непредсказуемым образом.

При нормальных обстоятельствах поток завершается одним из двух способов. Один из них — выход из потоковой функции. Возвращаемое ею значение считается значением, передаваемым из потока в программу. Второй способ— вызов специальной функции pthread_exit(). Это может быть сделано как в потоковой функции, так и в любой другой функции, явно или неявно вызываемой из нее. Аргумент функции pthread_exit() является значением, которое возвращается потоком.

4.1.1. Передача данных потоку

Потоковый аргумент — это удобное средство передачи данных потокам. Но поскольку его тип void*, данные содержатся не в самом аргументе. Он лишь должен указывать на какую-то структуру или массив. Лучше всего создать для каждой потоковой функции собственную структуру, в которой определялись бы "параметры", ожидаемые потоковой функцией.

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

Программа, приведенная в листинге 4.2, напоминает предыдущий пример. На этот раз создаются два потока: один отображает символы 'x', а другой — символы 'o'. Чтобы вывод на экран не длился бесконечно, потокам передается дополнительный аргумент, определяющий, сколько раз следует отобразить символ. Одна и та же функция char_print() эксплуатируется обоими потоками, но каждый из них конфигурируется независимо с помощью структуры char_print_parms.

Листинг 4.2. (thread-create2.c) Создание двух потоков

#include <pthread.h>

#include <stdio.h>


/* Параметры для функции char_print(). */

struct char_print_parms {

 /* Отображаемый символ. */

 char character;

 /* Сколько раз его нужно отобразить. */

 int count;

};


/* Запись указанного числа символов в поток stderr. Аргумент

   PARAMETERS является указателем на структуру char_print_parms. */

void* char_print(void* parameters) {

 /* Приведение указателя к нужному типу. */

 struct char_print_parms* p =

  (struct char_print_parms*)parameters;

 int i;

 for (i = 0; i < p->count; ++i)

  fputc(p->character, stderr);

 return NULL;

}


/* Основная программа. */

int main() {

 pthread_t thread1_id;

 pthread_t thread2_id;

 struct char_print_parms thread1_args;

 struct char_print_parms thread2_args;


 /* Создание нового потока, отображающего 30000

    символов 'x'. */

 thread1_args.character = 'x';

 thread1_args.count = 30000;

 pthread_create(&thread1_id, NULL, &char_print, &thread1_args);


 /* Создание нового потока, отображающего 20000

    символов 'o'. */

 thread2_args.character = 'o';

 thread2_args.count = 20000;

 pthread_create(&thread2_id, NULL, &char_print, &thread2_args);

 return 0;

}

Но постойте! Приведенная программа имеет серьезную ошибку. Основной поток (выполняющий функцию main()) создает структуры thread1_args и thread2_args в виде локальных переменных, а затем передает указатели на них дочерним потокам. Что мешает Linux распланировать работу потоков так, чтобы функция main() завершилась до того, как будут завершены другие два потока? Ничего! Но если это произойдет, структуры окажутся удаленными из памяти, хотя оба потока все еще ссылаются на них.

4.1.2. Ожидание завершения потоков

Одно из решений описанной выше проблемы заключается в том, чтобы заставить функцию main() дождаться завершения обоих потоков. Нужна лишь функция наподобие wait(), которая работает не с процессами, а с потоками. Такая функция называется pthread_join(). Она принимает два аргумента: идентификатор ожидаемого потока и указатель на переменную void*, в которую будет записано значение, возвращаемое потоком. Если последнее не важно, задайте в качестве второго аргумента NULL.


Марк Митчелл читать все книги автора по порядку

Марк Митчелл - все книги автора в одном месте читать по порядку полные версии на сайте онлайн библиотеки mybooks.club.


Программирование для Linux. Профессиональный подход отзывы

Отзывы читателей о книге Программирование для Linux. Профессиональный подход, автор: Марк Митчелл. Читайте комментарии и мнения людей о произведении.

Прокомментировать
Подтвердите что вы не робот:*
Подтвердите что вы не робот:*
Все материалы на сайте размещаются его пользователями.
Администратор сайта не несёт ответственности за действия пользователей сайта..
Вы можете направить вашу жалобу на почту librarybook.ru@gmail.com или заполнить форму обратной связи.