Нейл Мэтью - Основы программирования в Linux
- Название:Основы программирования в Linux
- Автор:
- Жанр:
- Издательство:«БХВ-Петербург»
- Год:2009
- Город:Санкт-Петербург
- ISBN:978-5-9775-0289-4
- Рейтинг:
- Избранное:Добавить в избранное
-
Отзывы:
-
Ваша оценка:
Нейл Мэтью - Основы программирования в Linux краткое содержание
В четвертом издании популярного руководства даны основы программирования в операционной системе Linux. Рассмотрены: использование библиотек C/C++ и стандартных средств разработки, организация системных вызовов, файловый ввод/вывод, взаимодействие процессов, программирование средствами командной оболочки, создание графических пользовательских интерфейсов с помощью инструментальных средств GTK+ или Qt, применение сокетов и др. Описана компиляция программ, их компоновка c библиотеками и работа с терминальным вводом/выводом. Даны приемы написания приложений в средах GNOME® и KDE®, хранения данных с использованием СУБД MySQL® и отладки программ. Книга хорошо структурирована, что делает обучение легким и быстрым.
Для начинающих Linux-программистов
Основы программирования в Linux - читать онлайн бесплатно полную версию (весь текст целиком)
Интервал:
Закладка:
#include
int pthread_create(pthread_t * thread, pthread_attr_t *attr,
void *(*start_routine)(void *), void *arg);
Прототип выглядит внушительно, но функцию очень легко применять. Первый аргумент — указатель на переменную типа pthread_t
. Когда поток создан, в область памяти, на которую указывает эта переменная, записывается идентификатор. Этот идентификатор позволяет ссылаться на поток. Следующий аргумент задает атрибуты потока. Обычно нет нужды в особых атрибутах, и вы можете просто передать в этом аргументе NULL
. Позже в этой главе вы увидите, как применять атрибуты потока. В последних двух аргументах потоку передается функция, которую он должен начать выполнять, и аргументы, которые нужно передать этой функции.
void *(*start_routine)(void *)
Предыдущая строка просто говорит о том, что вы должны передать адрес функции, принимающей бестиповой указатель void
как параметр, и функция вернет указатель на void
. Следовательно, вы можете передать единственный аргумент любого типа и вернуть указатель на любой тип. Применение функции fork
заставит продолжить выполнение в том же месте, но с другим кодом возврата, в то время как использование нового потока непосредственно предоставит указатель на функцию, которую новый поток должен начать выполнять.
Возвращаемое значение равно 0 в случае успеха и номеру ошибки, если что-то пошло не так. В интерактивном справочном руководстве есть подробная информация об ошибочных ситуациях для этой и других функций, применяемых в данной главе.
pthread_create
как большинство функций семейства pthread_
относится к тем немногим функциям Linux, которые не соблюдают соглашение об использовании значения -1 для обозначения ошибок. Если нет полной уверенности, всегда безопаснее всего дважды проверить справочное руководство перед проверкой кода возврата.
Когда поток завершается, он вызывает функцию pthread_exit
, во многом так же, как процесс во время завершения вызывает exit
. Функция завершает вызванный поток, возвращая указатель на объект. Никогда не применяйте ее для возврата указателя на локальную переменную, потому что переменная перестает существовать, когда поток завершается, вызывая серьезную ошибку. Функция pthread_exit
объявляется следующим образом:
#include <���рthread.h>
void pthread_exit(void *retval);
Функция pthread_join
— эквивалент функции wait
, которую процессы применяют для ожидания дочерних процессов. Она объявляется так:
#include <���рthread.h>
int pthread_join(pthread_t th, void** thread_return);
Первый параметр — это поток, который следует ждать, идентификатор, который для вас добывает функция pthread_create
. Второй аргумент — указатель на указатель, который указывает на возвращаемое из потока значение. Как и pthread_create
, эта функция возвращает ноль в случае успешного завершения и код ошибки при сбое.
Выполните упражнение 12.1.
Данная программа создает один дополнительный поток, показывает, что он совместно с исходным потоком использует переменные и заставляет новый поток вернуть результат исходному потоку. Далее приведена программа thread1.с.
#include
#include
#include
#include
#include
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
через минуту.)
Интервал:
Закладка: