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

Скачивание начинается... Если скачивание не началось автоматически, пожалуйста нажмите на эту ссылку.
Жалоба
Напишите нам, и мы в срочном порядке примем меры.
Описание книги "Программирование для Linux. Профессиональный подход"
Описание и краткое содержание "Программирование для Linux. Профессиональный подход" читать бесплатно онлайн.
Данная книга в основном посвящена программированию в среде GNU/Linux. Авторы применяют обучающий подход, последовательно излагая самые важные концепции и методики использования расширенных возможностей системы GNU/Linux в прикладных программах. Читатели научатся писать программы, к интерфейсу которых привыкли пользователи Linux; освоят такие технологии, как многозадачность, многопотоковое программирование, межзадачное взаимодействие и взаимодействие с аппаратными устройствами; смогут улучшить свои программы, сделав их быстрее, надежнее и безопаснее; поймут особенности системы GNU/Linux, ее ограничения, дополнительные возможности и специфические соглашения.
Книга предназначена для программистов, уже знакомых с языком С и имеющих базовый опыт работы в GNU/Linux.
Предположим, создается программа обработки транзакций, которая ведет журнальный файл. В этот файл помещаются записи обо всех транзакциях, завершившихся на данный момент, чтобы в случае системного сбоя можно было восстановить целостность данных. Очевидно, не менее важна и целостность самого журнального файла: как только транзакция завершена, запись о ней должна быть немедленно занесена в дисковый файл.
Для реализации такого поведения ОС Linux предоставляет системный вызов fsync(). Эта функция принимает один аргумент — дескриптор записываемого файла — и принудительно переносит на диск все данные этого файла, находящиеся в кэш-буфере. Функция не завершается до тех пор, пока данные не окажутся на диске.
В листинге 8.3 показана функция, использующая данный системный вызов. Она записывает переданную ей строку в журнальный файл.
Листинг 8.3. (write_journal_entry.c) Запись строки в журнальный файл с последующей синхронизацией#include <fcntl.h>
#include <string.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <unistd.h>
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 уничтожает ее.
Листинг 8.4. (limit-cpu.c) Задание ограничения на использование нейтрального процессора#include <sys/resource.h>
#include <sys/time.h>
#include <unistd.h>
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, в которой указано, сколько пользовательского времени (в секундах) ушло на выполнение процесса. Это время, затраченное центральным процессором на выполнение программного кода, а не системных вызовов.
■ ru_stime. Здесь находится структура типа timeval, в которой указано, сколько системного времени (в секундах) ушло на выполнение процесса. Это время, затраченное центральным процессором на выполнение системных вызовов от имени данного процесса.
■ ru_maxrss. Это максимальный объем физической памяти, которую процесс занимал в какой-то момент своего выполнения.
В листинге 8.5 приведена функция, которая показывает, сколько пользовательского и системного времени потребил текущий процесс.
Листинг 8.5. (prinf-cpu-times.c) Определение пользовательского и системного времени, затраченного на выполнение текущего процесса#include <stdio.h>
#include <sys/resource.h>
#include <sys/time.h>
#include <unistd.h>
void print_cpu_time() {
struct rusage usage;
getrusage(RUSAGE_SELF, &usage);
printf("CPU time: %ld.%061d sec user, %ld.%061d sec system\n",
usage.ru_utime.tv_sec, usage.ru_utime.tv_usec,
usage.ru_stime.tv_sec, usage.ru_stime.tv_usec);
}
8.7, Функция gettimeofday(): системные часы
Функция gettimeofday() определяет текущее системное время. В качестве аргумента она принимает структуру типа timeval, в которую записывается значение времени (в секундах), прошедшее с начала эпохи UNIX (1-е января 1970 г., полночь по Гринвичу). Это значение разделяется на два поля. В поле tv_sec хранится целое число секунд, а в поле tv_usec — дополнительное число микросекунд. У функции есть также второй аргумент, который должен быть равен NULL. Функция объявлена в файле <sys/time.h>.
Результат, возвращаемый функцией gettimeofday(), мало подходит для отображения на экране, поэтому существуют библиотечные функции localtime() и strftime(), преобразующие это значение в нужный формат. Функция localtime() принимает указатель на число секунд (поле tv_sec структуры timeval) и возвращает указатель на структуру типа tm. Эта структура содержит поля, заполняемые параметрами времени в соответствии с локальным часовым поясом:
■ tm_hour, tm_min, tm_sec — текущее время (часы, минуты, секунды);
■ tm_year, tm_mon, tm_day — год, месяц, день;
■ tm_wday — день недели (значение 0 соответствует воскресенью);
■ tm_yday — день года;
■ tm_isdst — флаг, указывающий, учтено ли летнее время.
Функция strftime() на основании структуры tm создает строку, отформатированную по заданному правилу. Формат напоминает тот, что используется в функции printf(): указывается строка с кодами, определяющими включаемые поля структуры. Например, форматная строка вида
"%Y-%m-%d %Н:%М:%S"
соответствует такому результату:
2001-01-14 13:09:42
Функции strftime() необходимо задать указатель на текстовый буфер, куда будет помещена полученная строка, длину буфера, строку формата и указатель на структуру типа tm. Следует учесть, что ни функция localtime(), ни функция strftime() не учитывают дробную часть текущего времени (поле tv_usec структуры timeval). Об этом должен позаботиться программист.
Подписывайтесь на наши страницы в социальных сетях.
Будьте в курсе последних книжных новинок, комментируйте, обсуждайте. Мы ждём Вас!
Похожие книги на "Программирование для Linux. Профессиональный подход"
Книги похожие на "Программирование для Linux. Профессиональный подход" читать онлайн или скачать бесплатно полные версии.
Мы рекомендуем Вам зарегистрироваться либо войти на сайт под своим именем.
Отзывы о "Марк Митчелл - Программирование для Linux. Профессиональный подход"
Отзывы читателей о книге "Программирование для Linux. Профессиональный подход", комментарии и мнения людей о произведении.