Нейл Мэтью - Основы программирования в Linux
- Название:Основы программирования в Linux
- Автор:
- Жанр:
- Издательство:«БХВ-Петербург»
- Год:2009
- Город:Санкт-Петербург
- ISBN:978-5-9775-0289-4
- Рейтинг:
- Избранное:Добавить в избранное
-
Отзывы:
-
Ваша оценка:
Нейл Мэтью - Основы программирования в Linux краткое содержание
В четвертом издании популярного руководства даны основы программирования в операционной системе Linux. Рассмотрены: использование библиотек C/C++ и стандартных средств разработки, организация системных вызовов, файловый ввод/вывод, взаимодействие процессов, программирование средствами командной оболочки, создание графических пользовательских интерфейсов с помощью инструментальных средств GTK+ или Qt, применение сокетов и др. Описана компиляция программ, их компоновка c библиотеками и работа с терминальным вводом/выводом. Даны приемы написания приложений в средах GNOME® и KDE®, хранения данных с использованием СУБД MySQL® и отладки программ. Книга хорошо структурирована, что делает обучение легким и быстрым.
Для начинающих Linux-программистов
Основы программирования в Linux - читать онлайн бесплатно полную версию (весь текст целиком)
Интервал:
Закладка:
Аргумент nfds
задает количество проверяемых файловых дескрипторов, имеются в виду дескрипторы от 0 до nfds-1
. Каждое из трех множеств дескрипторов может оказаться пустым указателем, тогда связанный с ним тест не выполняется.
Функция select
вернет управление, если какой-либо из дескрипторов в множестве readfds
готов к чтению, какой-нибудь дескриптор из множества writefds
готов к записи или у одного из дескрипторов множества errorfd
есть состояние ошибки. Если ни одно из условий не соблюдается, select
вернет управление после промежутка времени, заданного timeout
. Если параметр timeout
— пустой указатель и нет активности на сокетах, вызов может быть заблокирован на неопределенное время.
Когда select
возвращает управление программе, множества дескрипторов будут модифицированы для того, чтобы указать на готовые к чтению или записи или имеющие ошибки дескрипторы. Для их проверки следует использовать макрос FD_ISSET
, позволяющий определить, какие дескрипторы требуют внимания. Можно изменить значение timeout для того, чтобы показать время, остающееся до следующего превышения времени ожидания, но такое поведение не задано стандартом X/Open. При превышении времени ожидания все множества дескрипторов будут очищены.
Вызов select возвращает общее количество дескрипторов в модифицированных множествах. В случае сбоя он вернет -1 и установит значение переменной errno
, описывающее ошибку. Возможные ошибки — EBADF
для неверных дескрипторов, EINTR
для возврата из-за прерывания и EINVAL
для некорректных значений параметров nfds
или timeout
.
Несмотря на то, что Linux модифицирует структуру, на которую указывает timeout
, фиксируя оставшееся неиспользованное время, большинство версий UNIX этого не делают. Большая часть существующего программного кода, применяющего функцию select
, инициализирует структуру типа timeval
и затем продолжает использовать ее без обновления содержимого. В системе Linux этот код может выполняться некорректно, поскольку ОС Linux изменяет структуру timeval
при каждом истечении отведенного времени ожидания. Если вы пишете или переносите программный код, использующий функцию select
, следует учитывать эту разницу и всегда повторно инициализировать время ожидания. Имейте в виду, что оба подхода корректны, они просто разные!
Выполните упражнение 15.8.
select
Далее для демонстрации применения функции select приведена программа select.c. Более сложный пример вы увидите чуть позже. Программа читает данные с клавиатуры (стандартный ввод — дескриптор 0) со временем ожидания 2,5 секунды. Данные читаются только тогда, когда ввод готов. Естественно расширить программу, включив в зависимости от характера приложения другие дескрипторы, такие как последовательные каналы (serial lines) и сокеты.
1. Начните как обычно с директив include
и объявлений, а затем инициализируйте inputs
для обработки ввода с клавиатуры:
#include
#include
#include
#include
#include
#include
#include
int main() {
char buffer[128];
int result, nread;
fd_set inputs, testfds;
struct timeval timeout;
FD_ZERO(&inputs);
FD_SET(0, &inputs);
2. Подождите ввод из файла stdin в течение максимум 2,5 секунд:
while(1) {
testfds = inputs;
timeout.tv_sec = 2;
timeout.tv_usec = 500000;
result = select(FD_SETSIZE, &testfds, (fd_set *)NULL,
(fd_set*)NULL, &timeout);
3. Спустя это время проверьте result
. Если ввода не было, программа выполнит цикл еще раз. Если в нем возникла ошибка, программа завершается:
switch(result) {
case 0:
printf("timeout\n");
break;
case -1:
perror("select");
exit(1);
4. Если во время ожидания у вас наблюдаются некоторые действия, связанные с файловым дескриптором, читайте ввод из stdin и выводите его при каждом получении символа EOL (конец строки), до нажатой комбинации клавиш +:
default:
if (FD_ISSET(0, &testfds)) {
ioctl(0, FIONREAD, &nread);
if (nread == 0) {
printf("keyboard done\n");
exit(0);
}
nread = read(0, buffer, nread);
buffer[nread] = 0;
printf("read %d from keyboard: %s", nread, buffer);
}
break;
}
}
}
Во время выполнения эта программа каждые две с половиной секунды выводит строку timeout
. Если вы набираете данные на клавиатуре, она читает файл стандартного ввода и отображает то, что было набрано. В большинстве командных оболочек ввод направляется в программу при нажатии пользователем клавиши (или ) или клавиш управляющей последовательности, поэтому программа будет отображать ввод каждый раз, когда вы нажимаете клавишу . Учтите, что сама клавиша тоже читается и обрабатывается как любой другой символ (попробуйте выполнить ввод без нажатия клавиши, введя ряд символов, за которыми следует комбинация +).
$ ./select
timeout
hello
read 6 from keyboard: hello
fred
read 5 from keyboard: fred
timeout
^D
keyboard done
$
Как это работает
Программа применяет вызов select
для проверки состояния стандартного ввода. За счет корректировки значения времени ожидания программа каждые 2,5 секунды выводит сообщение об истечении времени ожидания. О нем свидетельствует возвращение 0 функцией select
. При достижении конца файла дескриптор стандартного ввода помечается флагом как готовый к вводу, но при этом нет символов, предназначенных для считывания.
Множественные клиенты
Ваша простая серверная программа может выиграть от применения select
для одновременной обработки множественных клиентов, не прибегая к помощи дочерних процессов. Используя этот метод в реальных приложениях, вы должны следить за тем, чтобы другие клиенты не ждали слишком долго, пока вы обрабатываете первого подключившегося клиента.
Сервер может применять функцию select
одновременно к сокету, ожидающему запросы на подключение, и к сокетам клиентских соединений. Как только активность зафиксирована, можно использовать макрос FD_ISSET
для проверки в цикле всех возможных файловых дескрипторов и выявления активных среди них.
Если сокет, ожидающий запросов на подключение, готов к вводу, это означает, что клиент пытается подсоединиться, и вы можете вызывать функцию accept
без риска блокировки. Если клиентский дескриптор указывает на готовность, это означает, что есть запрос клиента, ждущий, что вы сможете прочесть и обработать его. Чтение 0 байтов означает, что клиентский процесс завершился, и вы можете закрыть сокет и удалить его из множества своих дескрипторов.
Интервал:
Закладка: