Марк Митчелл - Программирование для Linux. Профессиональный подход
- Название:Программирование для Linux. Профессиональный подход
- Автор:
- Жанр:
- Издательство:Вильямс
- Год:2002
- Город:Москва
- ISBN:5-8459-0243-6
- Рейтинг:
- Избранное:Добавить в избранное
-
Отзывы:
-
Ваша оценка:
Марк Митчелл - Программирование для Linux. Профессиональный подход краткое содержание
Данная книга в основном посвящена программированию в среде GNU/Linux. Авторы применяют обучающий подход, последовательно излагая самые важные концепции и методики использования расширенных возможностей системы GNU/Linux в прикладных программах. Читатели научатся писать программы, к интерфейсу которых привыкли пользователи Linux; освоят такие технологии, как многозадачность, многопотоковое программирование, межзадачное взаимодействие и взаимодействие с аппаратными устройствами; смогут улучшить свои программы, сделав их быстрее, надежнее и безопаснее; поймут особенности системы GNU/Linux, ее ограничения, дополнительные возможности и специфические соглашения.
Книга предназначена для программистов, уже знакомых с языком С и имеющих базовый опыт работы в GNU/Linux.
Программирование для Linux. Профессиональный подход - читать онлайн бесплатно полную версию (весь текст целиком)
Интервал:
Закладка:
#include
#include
#include
#include
#include
#include
#define FILE_LENGTH 0x100
/* получение случайного числа в диапазоне [low,high]. */
int random_range(unsigned const low, unsigned const high) {
unsigned const range = high - low + 1;
return
low + (int)(((double)range) * rand() / (RAND_MAX + 1.0));
}
int main (int argc, char* const argv[]) {
int fd;
void* file_memory;
/* Инициализация генератора случайных чисел. */
srand(time(NULL));
/* подготовка файла, размер которого будет достаточен для
записи беззнакового целого числа. */
fd = open(argv[1], O_RDWR | O_CREAT, S_IRUSR | S_IWUSR);
lseek(fd, FILE_LENGTH+1, SEEK_SET);
write(fd, "", 1);
lseek(fd, 0, SEEK_SET);
/* Создание отображаемой области. */
file_memory =
mmap(0, FILE_LENGTH, PROT_WRITE, MAP_SHARED, fd, 0);
close(fd);
/* Запись случайного числа в отображаемую память. */
sprintf((char*)file_memory,
"%d\n", random_range(-100, 100));
/* Освобождение памяти (не обязательно, так как программа
завершается). */
munmap(file_memory, FILE_LENGTH);
return 0;
}
Программа mmap-write
пытается открыть файл и, если он не существует, создает его. Третий аргумент функции open()
указывает на то, что файл доступен для чтения/записи. Поскольку длина файла неизвестна, с помощью функции lseek()
мы убеждаемся в том, что файл имеет достаточную длину для записи беззнакового целого числа, а затем возвращаемся в начало файла.
Программа закрепляет файл за областью памяти и закрывает его дескриптор, так как в нем больше нет необходимости. После этого программа записывает случайное число в отображаемую память, т.е. в файл, и освобождает память. В принципе, вызывать функцию munmap()
нет необходимости, так как ОС Linux автоматически освободит память при завершении программы.
#include
#include
#include
#include
#include
#include
#define FILE_LENGTH 0x100
int main(int argc, char* const argv[]) {
int fd;
void* file_memory;
int integer;
/* Открытие файла. */
fd = open(argv[1], O_RDWR, S_IRUSR | S_IWUSR);
/* Создание отображаемой области. */
file_memory =
mmap(0, FILE_LENGTH, PROT_READ | PROT_WRITE,
MAP_SHARED, fd, 0);
close(fd);
/* Чтение целого числа и вывод его на экран. */
sscanf(file_memory, "%d", &integer);
printf("value: %d\n", integer);
/* Удваиваем число и записываем его обратно в файл. */
sprintf((char*)file_memory, "%d\n", 2 * integer);
/* Освобождение памяти (не обязательно, так как программа
завершается). */
munmap(file_memory, FILE_LENGTH);
return 0;
}
Программа mmap-read
читает число из файла, а затем удваивает его и записывает обратно в файл. Сначала файл открывается для чтения/записи. Поскольку предполагается, что файл содержит число, проверка с помощью функции lseek()
, как в предыдущей программе, не требуется. Чтение содержимого памяти и его анализ выполняет функция lseek()
. Функция sprintf()
форматирует число и записывает его в память.
Ниже показан пример запуска обеих программ. Им на вход передается файл /tmp/integer-file
.
% ./mmap-write /tmp/integer-file
% cat /tmp/integer-file
42
% ./mmap-read /tmp/integer-file
value: 42
% cat /tmp/integer-file
84
Обратите внимание: значение 42 оказалось записано в файл на диске, хотя функция write()
не вызывалась. Последующее чтение файла осуществлялось без функции read()
. Целое число записывалось в файл и извлекалось из него в текстовом виде (с помощью функций sprintf()
и sscanf()
). Это сделано исключительно в демонстрационных целях. В действительности отображаемый файл может содержать не только текст, но и двоичные данные.
5.3.3. Совместный доступ к файлу
Процессы могут взаимодействовать друг с другом через области отображаемой памяти, связанные с одним и тем же файлом. Если в функции mmap()
указать флаг MAP_SHARED
, все данные, заносимые в отображаемую память, будут немедленно записываться в файл, т.е. становиться видимыми другим процессам. При отсутствии этого флага ОС Linux может осуществлять предварительную буферизацию записываемых данных.
С другой стороны, с помощью функции msync()
можно заставить операционную систему перенести содержимое буфера в дисковый файл. Первые два параметра этой функции такие же, как и в функции munmap()
. Третий параметр может содержать следующие флаги.
■ MS_ASYNC
. Операция обновления ставится в очередь планировщика и будет выполнена, но не обязательно до того, как функция завершится.
■ MS_SYNC
. Операция обновления выполняется немедленно. До ее завершения функция блокируется. Флаги MS_ASYNC
и MS_SYNC
нельзя указывать одновременно.
■ MS_INVALIDATE
. Все остальные отображаемые области помечаются как недействительные и подлежащие обновлению.
Следующая функция обновляет файл, область отображения которого начинается с адреса mem_addr
и имеет длину mem_length
:
msync(mem_addr, mem_length, MS_SYNC | MS_INVALIDATE);
Как и в случае совместного использования сегментов памяти, при работе с отображаемыми областями необходимо придерживаться определенного порядка во избежание конкуренции. Например, можно создать семафор, который позволит только одному процессу обращаться к отображаемой памяти в конкретный момент времени. Можно также воспользоваться функцией fcntl()
и поставить на файл блокировку чтения или записи (об этом рассказывается в разделе 8.3, "Функция fcntl(): блокировки и другие операции над файлами").
5.3.4. Частные отображаемые области
Если в функции mmap()
указан флаг MAP_PRIVATE
, отображаемая область создается в режиме "копирование при записи". Любые операции записи в эту область имеют эффект только в адресном пространстве текущего процесса. Другие процессы, связанные с тем же самым отображаемым файлом, не узнают об изменениях. Изменения заносятся не на страницу, доступную всем процессам, а в частную копию этой страницы. Все последующие операции чтения и записи в данном процессе будут выполняться по отношению к этой копии.
5.3.5. Применения функции mmap()
Функция mmap()
может использоваться не только для организации взаимодействия процессов. Часто она выступает в качестве замены функциям read()
и write()
. Например, вместо того чтобы непосредственно загружать содержимое файла в память, программа может связать файл с отображаемой памятью и сканировать его путем обращения к памяти. Иногда это удобнее и быстрее, чем выполнять операции файлового ввода-вывода.
Интервал:
Закладка: