Марк Митчелл - Программирование для Linux. Профессиональный подход
- Название:Программирование для Linux. Профессиональный подход
- Автор:
- Жанр:
- Издательство:Вильямс
- Год:2002
- Город:Москва
- ISBN:5-8459-0243-6
- Рейтинг:
- Избранное:Добавить в избранное
-
Отзывы:
-
Ваша оценка:
Марк Митчелл - Программирование для Linux. Профессиональный подход краткое содержание
Данная книга в основном посвящена программированию в среде GNU/Linux. Авторы применяют обучающий подход, последовательно излагая самые важные концепции и методики использования расширенных возможностей системы GNU/Linux в прикладных программах. Читатели научатся писать программы, к интерфейсу которых привыкли пользователи Linux; освоят такие технологии, как многозадачность, многопотоковое программирование, межзадачное взаимодействие и взаимодействие с аппаратными устройствами; смогут улучшить свои программы, сделав их быстрее, надежнее и безопаснее; поймут особенности системы GNU/Linux, ее ограничения, дополнительные возможности и специфические соглашения.
Книга предназначена для программистов, уже знакомых с языком С и имеющих базовый опыт работы в GNU/Linux.
Программирование для Linux. Профессиональный подход - читать онлайн бесплатно полную версию (весь текст целиком)
Интервал:
Закладка:
В Linux имеется системный вызов flock()
, также реализующий операцию блокирования файла. Но у функции fcntl()
есть большое преимущество: она работает с файловыми системами NFS [28] NFS (Network File System) — популярная технология совместного использования файлов в сети.
(при условии, что сервер NFS имеет относительно недавнюю версию и сконфигурирован правильно). Так что. имея доступ к двум компьютерам, которые монтируют одну и ту же файловую систему через NFS, можно повторить показанный выше пример на двух разных машинах.
8.4. Функции fsync() и fdatasync(): очистка дисковых буферов
В большинстве операционных систем при записи в файл данные не передаются на диск немедленно. Вместо этого операционная система помещает их в резидентный кэш-буфер с целью сокращения числа обращений к диску и повышения оперативности программы. Когда буфер заполнится или произойдет какое-нибудь другое событие (например, истечет определенный промежуток времени), система запишет содержимое буфера на диск в ходе одной непрерывной операции.
В Linux тоже поддерживается такой тип кэширования. Обычно он способствует существенному повышению производительности. Но он же делает ненадежными программы, зависящие от целостности дисковых данных. Если система внезапно выйдет из строя, например вследствие сбоя ядра или отключения питания, любые данные, находящиеся в памяти и еще не записанные на диск, будут потеряны.
Предположим, создается программа обработки транзакций, которая ведет журнальный файл. В этот файл помещаются записи обо всех транзакциях, завершившихся на данный момент, чтобы в случае системного сбоя можно было восстановить целостность данных. Очевидно, не менее важна и целостность самого журнального файла: как только транзакция завершена, запись о ней должна быть немедленно занесена в дисковый файл.
Для реализации такого поведения ОС Linux предоставляет системный вызов fsync()
. Эта функция принимает один аргумент — дескриптор записываемого файла — и принудительно переносит на диск все данные этого файла, находящиеся в кэш-буфере. Функция не завершается до тех пор, пока данные не окажутся на диске.
В листинге 8.3 показана функция, использующая данный системный вызов. Она записывает переданную ей строку в журнальный файл.
#include
#include
#include
#include
#include
const char* journal_filename = "journal.log";
void write_journal_entry(char* entry) {
int fd =
open(journal_filename,
O_WRONLY | O_CREAT | O_APPEND, 0660);
write(fd, entry, strlen(entry));
write(fd, "\n", 1);
fsync(fd);
close(fd);
}
Аналогичное действие выполняет другой системный вызов: fdatasync()
. Но если функция fsync()
гарантирует, что дата модификации файла будет обновлена, то функция fdatasync()
этого не делает, а лишь гарантирует запись данных. В принципе это означает, что функция fdatasync()
способна выполняться быстрее, чем fsync()
, так как ей требуется выполнить одну операцию записи на диск, а не две. Но в настоящее время в Linux обе функции работают одинаково, обновляя дату модификации.
Файл можно также открыть в режиме синхронного ввода-вывода , при котором все операции записи будут немедленно фиксироваться на диске. Для этого в функции open()
следует указать флаг O_SYNC
.
8.5. Функции getrlimit() и setrlimit(): лимиты ресурсов
Функции getrlimit()
и setrlimit()
позволяют процессу определять и задавать лимиты использования системных ресурсов. Аналогичные действия выполняет команда ulimit
, которая ограничивает доступ запускаемых пользователем программ к ресурсам.
У каждого ресурса есть два лимита: жесткий и нежесткий . Второе значение никогда не может быть больше первого, и лишь процессы с привилегиями супер пользователя имеют право менять жесткий лимит. Обычно приложение уменьшает нежесткий лимит, ограничивая потребление системных ресурсов.
Обе функции принимают два аргумента: код, задающий тип ограничения, и указатель на структуру типа rlimit
. Функция getrlimit()
заполняет поля этой структуры, тогда как функция setrlimit()
проверяет их и соответствующим образом меняет лимит. У структуры rlimit
два поля: в поле rlim_cur
содержится значение нежесткого лимита, а в поле rlim_max
— значение жесткого лимита.
Ниже перечислены коды наиболее полезных лимитов, допускающих возможность изменения.
■ RLIMIT_CPU
. Это максимальный интервал времени центрального процессора (в секундах), занимаемый программой. Именно столько времени отводится программе на доступ к процессору. В случае превышения данного ограничения программа будет завершена по сигналу SIGXCPU
.
■ RLIMIT_DATA
. Это максимальный объем памяти, который программа может запросить для своих данных. Запросы на дополнительную память будут отвергнуты системой.
■ RLIMIT_NPROC
. Это максимальное число дочерних процессов, которые могут быть запущены пользователем. Если процесс вызывает функцию fork()
, а лимит уже исчерпал, функция завершается ошибкой.
■ RLIMIT_NOFILE
. Это максимальное число файлов, которые могут быть одновременно открыты процессом.
Программа, приведенная в листинге 8.4, задает односекундный лимит использования центрального процессора, после чего переходит в бесконечный цикл. Как только программа превышает установленный ею же лимит, ОС Linux уничтожает ее.
#include
#include
#include
int main() {
struct rlimit rl;
/* Определяем текущие лимиты. */
getrlimit(RLIMIT_CPU, &rl);
/* Ограничиваем время доступа к процессору
одной секундой. */
rl.rlim_cur = 1;
setrlimit(RLIMIT_CPU, &rl);
/* Переходим в бесконечный цикл. */
while(1);
return 0;
}
Когда программа завершается по сигналу SIGXCPU
, интерпретатор команд выдает поясняющее сообщение:
% ./limit_cpu
CPU time limit exceeded
8.6. Функция getrusage(): статистика процессов
Функция getrusage()
запрашивает у ядра статистику работы процессов. Если первый аргумент функции равен RUSAGE_SELF
, процесс получит информацию о самом себе. Если же первым аргументом является константа RUSAGE_CHILDREN
, будет выдана информация обо всех его завершившихся дочерних процессах. Второй аргумент — это указатель на структуру типа rusage
, в которую заносятся статистические данные.
Перечислим наиболее интересные поля этой структуры.
■ ru_utime
. Здесь находится структура типа timeval
, в которой указано, сколько пользовательского времени (в секундах) ушло на выполнение процесса. Это время, затраченное центральным процессором на выполнение программного кода, а не системных вызовов.
Интервал:
Закладка: