Литмир - Электронная Библиотека
Содержание  
A
A

Вызов

fcntl
также позволяет реализовать блокировку файла. См. более подробную информацию в разделе 2 интерактивного справочного руководства или главу 7, в которой мы обсуждаем блокировку файлов.

mmap

Система UNIX предоставляет полезное средство, позволяющее программам совместно использовать память, и, к счастью, оно включено в версию 2.0 и более поздние версии ядра Linux. Функция

mmap
(для отображения памяти) задает сегмент памяти, который может читаться двумя или несколькими программами и в который они могут записывать данные. Изменения, сделанные одной программой, видны всем остальным.

Вы можете применить то же самое средство для работы с файлами, заставив все содержимое файла на диске выглядеть как массив в памяти. Если файл состоит из записей, которые могут быть описаны структурами на языке С, вы сможете обновлять файл с помощью методов доступа к массиву структур.

Это становится возможным благодаря применению сегментов виртуальной памяти с набором особых прав доступа. Чтение из сегмента и запись в него заставляет операционную систему читать соответствующую часть файла на диске и писать данные в нее.

Функция mmap создает указатель на область памяти, ассоциированную с содержимым файла, доступ к которому осуществляется через открытый дескриптор файла.

<b>#include &lt;sys/mman.h&gt;</b>

<b>void *mmap(void *addr, size_t len, int prot, int flags, int fildes, off_t off);</b>

Изменить начальную позицию порции данных файла, к которым выполняется обращение через совместно используемый сегмент, можно, передавая параметр

off
. Открытый дескриптор файла задается в параметре
fildes
. Объем данных, к которым возможен доступ (т. е. размер сегмента памяти), указывается в параметре
len
.

Параметр

addr
можно использовать для запроса конкретного адреса памяти. Если он равен нулю, результирующий указатель формируется автоматически. Последний вариант рекомендуется, потому что в противном случае трудно добиться переносимости; диапазоны доступных адресов в разных системах отличаются.

Параметр

prot
используется для установки прав доступа к сегменту памяти. Он представляет собой результат поразрядной операции or, примененной к следующим константам:

PROT_READ
— сегмент может читаться;

PROT_WRITE
— в сегмент можно писать;

PROT_EXEC
— сегмент может выполняться;

PROT_NONE
— к сегменту нет доступа.

Параметр

flags
контролирует, как изменения, сделанные программой в сегменте, отражаются в других местах; его возможные значения приведены в табл. 3.7.

Таблица 3.7

Константа Описание
MAP_PRIVATE
Сегмент частный, изменения локальные
MAP_SHARED
Изменения сегмента переносятся в файл
MAP_FIXED
Сегмент должен располагаться по заданному адресу
addr

Функция

msync
вызывает запись изменений в части или во всем сегменте памяти обратно а отображенный файл (или считывание из файла).

<b>#include &lt;sys/mman.h&gt;</b>

<b>int msync(void *addr, size_t len, int flags);</b>

Корректируемая часть сегмента задается передачей начального адреса

addr
и размера
len
. Параметр
flags
управляет способом выполнения корректировки с помощью вариантов, приведенных в табл. 3.8.

Таблица 3.8

Константа Описание
MS_ASYNC
Выполнять запись асинхронно
MS_SYNC
Выполнять запись синхронно
MS_INVALIDATE
Обновить другие отражения этого файла так, чтобы они содержали изменения, внесенные этим вызовом

Функция

munmap
освобождает сегмент памяти.

<b>#include &lt;sys/mman.h&gt;</b>

<b>int munmap(void *addr, size_t len);</b>

В программе mmap.с из упражнения 3.5 показан файл из структур, которые будут корректироваться с помощью функции

mmap
и обращений в стиле массива. Ядро Linux версий, меньших 2.0, не полностью поддерживает применение функции
mmap
. Программа работает корректно в системе Sun Solaris и других системах.

Упражнение 3.5. Применение функции
mmap

1. Начните с определения структуры

RECORD
и создайте
NRECORDS
вариантов, в каждый из которых записывается собственный номер. Они будут добавлены в конец файла records.dat.

#include &lt;unistd.h&gt;

#include &lt;stdio.h&gt;

#include &lt;sys/mman.h&gt;

#include &lt;fcntl.h&gt;

#include &lt;stdlib.h&gt;

typedef struct {

 int integer;

 char string[24];

} RECORD;

#define NRECORDS (100)

int main() {

 RECORD record, *mapped;

 int i, f;

 FILE *fp;

 fp = fopen(&quot;records.dat&quot;, &quot;w+&quot;);

 for (i=0; i&lt;NRECORDS; i++) {

  record.integer = i;

  sprintf(record.string, &quot;RECORD-%d&quot;, i);

  fwrite(&amp;record, sizeof(record), 1, fp);

 }

 fclose(fp);

2. Далее измените целое значение записи с 43 на 143 и запишите его в строку 43-й записи.

62
{"b":"285844","o":1}