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

Тут можно читать онлайн Марк Митчелл - Программирование для Linux. Профессиональный подход - бесплатно полную версию книги (целиком) без сокращений. Жанр: comp-programming, издательство Вильямс, год 2002. Здесь Вы можете читать полную версию (весь текст) онлайн без регистрации и SMS на сайте лучшей интернет библиотеки ЛибКинг или прочесть краткое содержание (суть), предисловие и аннотацию. Так же сможете купить и скачать торрент в электронном формате fb2, найти и слушать аудиокнигу на русском языке или узнать сколько частей в серии и всего страниц в публикации. Читателям доступно смотреть обложку, картинки, описание и отзывы (комментарии) о произведении.
  • Название:
    Программирование для Linux. Профессиональный подход
  • Автор:
  • Жанр:
  • Издательство:
    Вильямс
  • Год:
    2002
  • Город:
    Москва
  • ISBN:
    5-8459-0243-6
  • Рейтинг:
    3.6/5. Голосов: 101
  • Избранное:
    Добавить в избранное
  • Отзывы:
  • Ваша оценка:
    • 80
    • 1
    • 2
    • 3
    • 4
    • 5

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

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

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

Книга предназначена для программистов, уже знакомых с языком С и имеющих базовый опыт работы в GNU/Linux.

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

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

Интервал:

Закладка:

Сделать

#include

/* Выделение временного буфера. */

void* allocate_buffer(size_t size) {

return malloc(size);

}

/* Удаление временного буфера. */

void deallocate_buffer(void* buffer) {

free(buffer);

}

void do_some_work() {

/* Выделение временного буфера. */

void* temp_buffer = allocate_buffer(1024);

/* Регистрация обработчика очистки для данного буфера. Этот

обработчик будет удалять буфер при завершении или отмене

потока. */

pthread_cleanup_push(deallocate_buffer, temp_buffer);

/* Выполнение других действий... */

/* Отмена регистрации обработчика. Поскольку функции передается

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

deallocate_buffer(). */

pthread_cleanup_pop(1);

}

В данном случае функции pthread_cleanup_pop()передается ненулевой аргумент, поэтому функция очистки deallocate_buffer()вызывается автоматически. В данном простейшем случае можно было в качестве обработчика непосредственно использовать стандартную библиотечную функцию free().

4.3.2. Очистка потоковых данных в C++

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

Тем не менее, если поток вызывает функцию pthread_exit(), среда выполнения C++ не может гарантировать вызов деструкторов для всех автоматических переменных, находящихся в стеке потока. Чтобы этого добиться, нужно вызвать функцию pthread_exit()в рамках конструкции try/catch, охватывающей все тело потоковой функции. При этом перехватывается специальное исключение ThreadExitException.

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

Листинг 4.9. ( cxx-exit.cpp ) Безопасное завершение потока в C++

#include

class ThreadExitException {

public:

/* Конструктор, принимающий аргумент RETURN_VALUE, в котором

содержится возвращаемое потоком значение. */

ThreadExitException(void* return_value) :

thread_return_value_(return_value) {

}

/* Реальное завершение потока. В программу возвращается

значение, переданное конструктору. */

void* DoThreadExit() {

pthread_exit(thread_return_value_);

}

private:

/* Значение, возвращаемое в программу при завершении потока. */

void* thread_return_value_;

};

void do_some_work() {

while (1) {

/* Здесь выполняются основные действия... */

if (should_exit_thread_immediately())

throw ThreadExitException(/* поток возвращает */NULL);

}

}

void* thread_function(void*) {

try {

do_some_work();

} catch (ThreadExitException ex) {

/* Возникла необходимость завершить поток. */

ex.DoThreadExit();

}

return NULL;

}

4.4. Синхронизация потоков и критические секции

Программирование потоков — нетривиальная задача, ведь большинство потоков выполняется одновременно. К примеру, невозможно определить, когда система предоставит доступ к процессору одному потоку, а когда — другому. Длительность этого доступа может быть как достаточно большой, так и очень короткой, в зависимости от того, как часто система переключает задания. Если в системе есть несколько процессоров, потоки могут выполняться одновременно в буквальном смысле.

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

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

4.4.1. Состояние гонки

Предположим, что в программу поступает группа запросов, которые обрабатываются несколькими одновременными потоками. Очередь запросов представлена связанным списком объектов типа struct job.

Когда каждый поток завершает свою операцию, он обращается к очереди и проверяет, есть ли в ней еще необработанные запросы. Если указатель job_queueне равен NULL, поток удаляет из списка самый верхний элемент и перемещает указатель на следующий элемент. Потоковая функции, работающая с очередью заданий, представлена в листинге 4.10.

Листинг 4.10. ( job-queue1.c ) Потоковая функция, работающая с очередью заданий

#include

struct job {

/* Ссылка на следующий элемент связанного списка. */

struct job* next;

/* Другие поля, описывающие требуемую операцию... */

};

/* Список отложенных заданий. */

struct job* job_queue;

/* Обработка заданий до тех пор, пока очередь не опустеет. */

void* thread_function(void* arg) {

while (job_queue != NULL) {

/* Запрашиваем следующее задание. */

struct job* next_job = job_queue;

/* Удаляем задание из списка. */

job_queue = job_queue->next;

/* выполняем задание. */

process_job(next_job);

/* Очистка. */

free(next_job);

}

return NULL;

}

Теперь предположим, что два потока завершают свои операции примерно в одно и то же время, а в очереди остается только одно задание. Первый поток проверяет, равен ли указатель job_queueзначению NULL, и, обнаружив, что очередь не пуста, входит в цикл, где сохраняет указатель на объект задания в переменной next_job. В этот момент Linux прерывает первый поток и активизирует второй. Он тоже проверяет указатель job_queue, устанавливает, что он не равен NULL, и записывает тот же самый указатель в свою переменную next_job. Увы, теперь мы имеем два потока, выполняющих одно и то же задание.

Читать дальше
Тёмная тема
Сбросить

Интервал:

Закладка:

Сделать


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

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




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


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


Понравилась книга? Поделитесь впечатлениями - оставьте Ваш отзыв или расскажите друзьям

Напишите свой комментарий
x