Майкл Джонсон - Разработка приложений в среде Linux. Второе издание
- Название:Разработка приложений в среде Linux. Второе издание
- Автор:
- Жанр:
- Издательство:Вильямс
- Год:2007
- Город:Москва
- ISBN:978-5-8459-1143-8
- Рейтинг:
- Избранное:Добавить в избранное
-
Отзывы:
-
Ваша оценка:
Майкл Джонсон - Разработка приложений в среде Linux. Второе издание краткое содержание
Книга известных профессионалов в области разработки коммерческих приложений в Linux представляет собой отличный справочник для широкого круга программистов в Linux, а также тех разработчиков на языке С, которые перешли в среду Linux из других операционных систем. Подробно рассматриваются концепции, лежащие в основе процесса создания системных приложений, а также разнообразные доступные инструменты и библиотеки. Среди рассматриваемых в книге вопросов можно выделить анализ особенностей применения лицензий GNU, использование свободно распространяемых компиляторов и библиотек, системное программирование для Linux, а также написание и отладка собственных переносимых библиотек. Изобилие хорошо документированных примеров кода помогает лучше усвоить особенности программирования в Linux.
Книга рассчитана на разработчиков разной квалификации, а также может быть полезна для студентов и преподавателей соответствующих специальностей.
Разработка приложений в среде Linux. Второе издание - читать онлайн бесплатно полную версию (весь текст целиком)
Интервал:
Закладка:
Как и блокировочные файлы, блокировки POSIX также являются рекомендательными. Linux, как и System V, предоставляет обязательный вариант блокирования записей, который можно использовать, но нарушая при этом переносимость. Блокирование файлов может работать или не работать в сетевой файловой системе (NFS). В последних версиях Linux блокирование файлов работает в NFS, если на всех машинах, участвующих в блокировке, выполняется демон блокировки NFS lockd
.
При блокировке записей используются два типа блокировок: блокировка чтенияи блокировка записи. Блокировки чтения также известны как разделяемые блокировки, поскольку несколько процессов могут одновременно удерживать блокировки чтения на одной и той же области. Для нескольких процессов чтение структуры данных, которая не обновляется, безопасно всегда. Когда процессу необходимо записать файл, ему понадобится блокировка записи (или эксклюзивная блокировка). Только один процесс может удерживать блокировку на определенной записи, и пока блокировка записи существует, блокировки чтения не допускаются. Это гарантирует, что процесс не повлияет на модули чтения, пока будет осуществлять запись в область.
Множество блокировок одного процесса никогда не конфликтуют друг с другом [90] Эта ситуация более сложна для потоков. Многие ядра и библиотеки Linux рассматривают потоки как разные процессы, что увеличивает потенциал возникновения конфликтов файловых блокировок между потоками (а это не совместимо со стандартной моделью потоков POSIX). Linux предлагает более традиционную модель потоков, при которой файловые блокировки разделяются между всеми потоками одного процесса, но в многопоточных программах лучше применять потоковые механизмы блокировки POSIX, а не полагаться на поведение файловых блокировок.
.
Если процесс имеет блокировку чтения на байтах 200—250 и пытается установить блокировку записи на байты 200–225, ему это удастся. Исходная блокировка смещается и становится блокировкой чтения на байтах 226–250, а новая блокировка записи устанавливается на байты 200–225 [91] Эта манипуляция блокировками происходит атомарно — не имеет значения, какая часть области разблокирована.
. Это позволяет предотвратить взаимоблокировку одного процесса (хотя ситуация взаимоблокировки нескольких процессов по-прежнему возможна).
Блокирование записей POSIX осуществляется с помощью системного вызова fcntl()
. В главе 11 было показано, что fcntl()
выглядит следующим образом.
#include
int fcntl (int fd, int command, long arg);
Для всех операций блокировки третий параметр ( arg
) указывает на структуру struct flock
, представленную ниже.
#include
struct flock {
short l_type;
short l_whence;
off_t l_start;
off_t l_len;
pid_t l_pid;
};
Первый элемент, l_type
, определяет тип установленной блокировки.
F_RDLCK |
Устанавливается блокировка чтения (разделяемая). |
F_WRLCK |
Устанавливается блокировка записи (эксклюзивная). |
F_UNLCK |
Снимается существующая блокировка. |
Следующие два элемента, l_whence
и l_start
, определяют начало области тем же способом, что и файловые смещения, передаваемые в lseek()
. l_whence
сообщает о способе интерпретации l_start
и принимает одно из значений SEEK_SET
, SEEK_CUR
или SEEK_END
; более подробно эти значения рассматривались в главе 11. Следующий элемент, l_len
, сообщает размер блокировки в байтах. Если l_len
равно 0, считается, что блокировка распространяется до конца файла. Последний элемент, l_pid
, используется только тогда, когда запрашиваются блокировки. Он устанавливается в идентификатор процесса, владеющего запрашиваемой блокировкой.
Существуют три команды fcntl()
, относящиеся к блокировке файла. Они передаются fcntl()
во втором аргументе, fcntl()
возвращает -1
в случае ошибки и 0
— в противном случае. Ниже перечислены допустимые значения параметра command
.
F_SETLK |
Устанавливает блокировку, описанную в arg . Если блокировку невозможно выдать из-за конфликта с блокировками других процессов, возвращается EAGAIN . Если l_type устанавливается в F_UNLCK , существующая блокировка снимается. |
F_SETLKW |
Подобно F_SETLK , но блокирует только при условии предоставления блокировки. Если сигнал поступает во время блокирования процесса, вызов fcntl() возвращает EAGAIN . |
F_GETLK |
Проверяет возможность выдачи описанной в arg блокировки. Если блокировка предоставляется, содержимое struct flock не меняется, кроме l_type , который устанавливается в F_UNLCK . Если блокировка не выдается, l_pid устанавливается в идентификатор процесса, содержащего конфликтующую блокировку. Значение 0 возвращается независимо от того, будет ли предоставлена блокировка. |
Хотя F_GETLK
позволяет процессу проверить, будет ли выдана блокировка, следующий код все еще не сможет получить блокировку.
fcntl(fd, F_GETLK, &lockinfo);
if (lockinfо.l_type != F_UNLCK) {
fprintf(stderr, "конфликт блокировок\n");
return 1;
}
lockinfо.l_type = F_RDLCK;
fcntl(fd, F_SETLK, &lockinfo);
Другой процесс мог заблокировать область между двумя вызовами fcntl()
, приводя к тому, что второму вызову fcntl()
не удается установить блокировку.
В качестве простого примера блокировки записей ниже приведена программа, которая открывает файл, устанавливает на нем блокировку чтения, освобождает блокировку чтения, устанавливает блокировку записи и закрывается. В промежутках между каждым из этих шагов программа ожидает, пока пользователь нажмет клавишу . Если получить блокировку не удается, программа отображает идентификатор процесса, содержащего конфликтующую блокировку, и запрашивает у пользователя о необходимости повторить попытку. Запуск этой программы на двух терминалах облегчит экспериментирование с правилами блокировок POSIX.
1: /* lock.с */
2:
3: #include
4: #include
5: #include
6: #include
7:
8: /* выводит сообщение и ожидает нажатия
9: пользователем клавиши */
10: void waitforuser(char * message) {
11: char buf[10];
12:
13: printf("%s", message);
14: fflush(stdout);
15:
16: fgets(buf, 9, stdin);
17: }
18:
19: /* Получает блокировку заданного типа на файловом дескрипторе fd.
20: Типом блокировки может быть F_UNLCK, F_RDLCK или F_WRLCK */
21: void getlock(int fd, int type) {
22: struct flock lockinfo;
23: char message[80];
24:
Интервал:
Закладка: