Способы организации файловых операций. Блокирование файлов

Скачать Viber 27.05.2019
Скачать Viber

Excel для Office 365 Word для Office 365 PowerPoint для Office 365 Excel 2019 Word 2019 PowerPoint 2019 Excel 2016 Word 2016 PowerPoint 2016 Excel 2013 Word 2013 PowerPoint 2013 Excel 2010 Word 2010 PowerPoint 2010 Office 2010 Меньше

Файлы, созданные в предыдущих версиях Office (например, документы Word 95), по умолчанию открываются в режиме защищенного просмотра с отключенными возможностями редактирования.

Функция блокировки файлов запрещает открывать файлы устаревших типов и приводит к их открытию в режиме защищенного просмотра (при этом команды "Сохранить" и "Открыть" отключены). В коде, который открывает и сохраняет файлы в устаревших форматах, есть уязвимости, которые могут быть использованы злоумышленниками. Таким образом, они представляют собой угрозу безопасности, которой следует по возможности избегать.

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

Ниже приведены примеры панели сообщений для блокировки файлов. Желтый значок щита указывает на то, что файл можно редактировать, а красный - на то, что это запрещено.

Редактирование заблокированного файла

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

На вкладке Файл выберите пункт Параметры .

Выберите пункт , нажмите кнопку и выберите пункт Параметры блокировки файлов .

Установите флажок .

Просмотр и изменение параметров блокировки файлов в центре управления безопасностью

Откройте приложение Office.

На вкладке Файл выберите пункт Параметры .

Выберите пункт Центр управления безопасностью , нажмите кнопку Параметры центра управления безопасностью... и выберите пункт Параметры блокировки файлов .

В списке Тип файла установите и снимите флажки Открыть и Сохранить для типов файлов, которые нужно заблокировать или разрешить.

Примечание: Флажок Открыть невозможно установить, если не установлен флажок Сохранить .

Описание параметров блокировки файлов

    Не открывать выбранные типы файлов. Файлы, отмеченные галочкой, нельзя открывать или открывать и сохранять. Если этот параметр установлен, при попытке выполнить запрещенную операцию выводится сообщение об ошибке.

    Открывать выбранные типы файлов в режиме защищенного просмотра. Файлы выбранных типов открываются в режиме защищенного просмотра. Кнопка Разрешить редактирование отключена на панели сообщений и в представлении Backstage.

    Открывать выбранные типы файлов в режиме защищенного просмотра и разрешать редактирование . Файлы выбранных типов открываются в режиме защищенного просмотра. Кнопка Разрешить редактирование включена на панели сообщений и в представлении Backstage.

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

Непосредственное использование в Unix только функций открытия, закрытия, записи в файл и чтения из файла не обеспечивает полных возможностей совместного использования файлов. Для управления совместным доступом к открытым файлам Unix содержит дополнительные средства, обеспечиваемые через системную функцию fcntl. Функция эта имеет прототип

int fcntl(int handle, int cmd, . . .).

Параметр cmd задает операции, которые необходимо выполнить над файлом, указанным аргументом handle . Третий аргумент этой функции, который может быть указан после cmd , зависит от конкретного значения операции cmd . Имеется целый ряд возможных значений для аргумента операции функции fcntl, но большинство из них не будет рассматриваться здесь. Ограничимся только значениеми, относящимися к взаимной блокировке файлов и их записей. В этом случае функция fcntl приобретает вид

int fcntl(int handle, int cmd, struct flock *ldata).

Для этого варианта имеем три основных значения аргумента cmd . Они обозначаются символическими константами F_SETLK, F_SETLKW и F_GETLK. Структуры flock данных описываются в заголовочном файле в виде

{short l _type; // тип блокировки

short l _whence; // код базовой позиции для отсчета смещения

off_t l _start; // смещение относительно базовой позиции

off_t l _len; // сколько байтов находится в заблокированной области

pid_t l _pid; // PID процесса, который блокировал файл

Сами символические константы операций блокировок обозначают следующее. Константа F_SETLK задает попытку применить блокировку к файлу и немедленно возвратить управление либо же отменить блокировку, если это действие задано типом блокировки, равным F_UNLCK. При неудачной попытке наложения блокировки с операцией, заданной константой F_SETLK, функция fcntl возвращает код -1. Константа F_SETLKW приказывает попытаться применить блокировку к файлу и приостановить работу, если блокировка уже наложена другим процессом. Константа F_GETLK делает запрос на получение описания блокировки, отвечающей данным в аргументе ldata (возвращаемая информация описывает первую блокировку, препятствующую наложению блокировки, которая задается структурой ldata ).

Код базовой позиции для отсчета смещения задает либо начальную позицию в файле (константой SEEK_SET), либо текущую позицию в нем (константой SEEK_CUR), либо позицию конца файла (константой SEEK_END).

В пояснение описанных деталей отметим, что средства Unix позволяют управлять совместным доступом не только ко всему файлу, но и к отдельным участкам его. В частности, разрешить другим процессам только читать отдельные участки файла, а другим, может быть, разрешить изменять их. Поэтому указанные средства содержат не только указание разрешения вида доступа или соответственно запрета (блокировки) доступа, но и описание участка, к которому относится такой запрет. Именно с этой целью в состав структуры flock включены поля l_whence , l_start , l_len , причем поле l_len задает длину участка, на который распространяется действие конкретного вызова функции fcntl ; поле l_start задает начальное смещение рассматриваемого участка относительно точки позиции, указанной параметром l_ whence . Последний, в свою очередь, значениями констант задает отсчет позиции относительно начала файла, относительно текущего положения указателя позиции в нем или относительно конца файла. В качестве указанных констант могут быть взяты соответственно значения 0, 1, 2 или именованные константы SEEK_SET, SEEK_CUR, SEEK_END из заголовочного файла stdio.h. Поле l_len может быть задано числом 0, тогда блокировка распространяется от указанного в структуре начала файла до его конца (причем при дальнейшем увеличении файла в процессе работы с ним эта блокировка распространяется дальше – до текущего конца файла).



В структуре данных flock тип блокировки, указываемый полем l_type , задается символическими константами, предварительно описанными в заголовочном файле. Эти константы следующие: F_RDLCK – установить на указанную в структуре область данных блокировку чтения; F_WRLCK – установить на указанную в структуре область данных блокировку записи; F_UNLCK – снять блокировку с указанной области. Функция fcntl может быть использована многократно для различных участков файла и для них с ее помощью могут быть установлены, изменены или сняты определенные виды блокировок.

Блокировка по чтению (константой F_RDLCK) может быть установлена только в том случае, если файл, на который она устанавливается текущей программой, открыт для чтения (т.е. с режимом O_RDONLY или O_RDWR). Блокировка по записи (константой F_WRLCK) может быть установлена только, если файл, на который она устанавливается текущей программой, открыт данной программой для записи (т.е. с режимом O_WRONLY или O_RDWR).

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

Блокировка по чтению на участок файла может устанавливаться независимо различными процессами, но блокировку по записи может установить только один процесс. Попытки других процессов установить такую блокировку, пока она не снята процессом, установившем ее, оказываются неудачными. Эта неудача проявляется в том, что при использовании операции SETLK функция fcntl возвращает значение ‑1, а при использовании операции SETLKW в функции fcntl процесс приостанавливается до снятия блокировки другим процессом.

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

Следующая программа, приведенная листингом 2.4.1, демонстрирует использование функций открытия файла, закрытия файла, записи в файл, задание ограничения совместного доступа и аналогична по выполняемым действиям программе в листинге 2.3.1, написанной для другой ОС.

#include

#include

{char buffer="Было прочитано ";

int fhandle;int fhandle;

char fname="myresult.txt";

struct flock lock={F_WRLCK, SEEK_SET, 0, 0};

fhandle=open(fname, O_WRONLY | O_CREAT | O_TRUNC, 0600);

fcntl(fhandle, F_SETLKW, &lock);

write(1, "Vvedite\n",8);

len=read(0, buffer+16, 80); // записываем вводимое после начального текста

write(fhandle, buffer, 16+len);

lock.l_type=F_UNLCK;

fcntl(fhandle, F_SETLK, &lock);

Листинг 2.4.1. Программа ограничения доступа к файлу в Unix

В этом примере значение поля l_type структуры данных lock типа flock задается равным константе F_WRLCK, т.е. указывается блокировка при записи данной программой, которая равносильна запрету как по чтению, так и по записи для других процессов. Начальный адрес участка задается на основе начальной позиции в файле (константа SEEK_SET в поле l_whence ) со смещением в l_start , равным нулю, т.е. указывается, что управляемый участок начинается с самого начала файла. Значение поля l_len задано нулевым, что равносильно указанию распространения действий до конца файла. Таким образом указано, что воздействию запрета на доступ для других процессов подлежит весь файл. Рассматриваемый запрет на запись осуществляется вызовом функции fcntl(fhandle, F_SETLKW, &lock) сразу после открытия файла. Если в последующие моменты времени до снятия этой блокировки другой процесс выполняет аналогичную функцию fcntl(fhandle, F_SETLKW, &lock), то он приостанавливается на этой функции до тех пор, пока блокировка не будет снята.

После записи в файл функция write задает отмену запрета на запись, установленного данным процессом. С этой целью выполняется функция fcntl(fhandle, F_SETLK, &lock), в параметре lock которой задано поле l_type , равное константе F_UNLCK, т.е. указывается отмена блокировки (того же участка, что и раньше был указан в этой структуре).

Заметим, что если не требуется принимать мер по управлению совместным использованием файла, то в программе для Unix достаточно просто не использовать функцию fcntl для этих целей. В частности, для упрощения рассматриваемого примера можно было отбросить из программы вызовы функции fcntl , описание и установки полей экземпляра lock структуры flock . В программах же для операционных систем MS Windows и OS/2 во всех случаях приходится использовать те же функции, что и в более сложном случае, причем с заданием всех их параметров.

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

BOOL LockFile(HANDLE hFile,

DWORD nNumberOfBytesToLockHigh).

Данная функция при удачном выполнении блокирует доступ к указанному в ней участку для всех других процессов. Эта функция предназначена в общем случае для работы с очень большими файлами, размер которых превосходит числа, задаваемые в формате DWORD (более чем 32-битные двоичные числа, что соответствует границе в 4Гбайта). Поэтому для задания смещения блокируемого участка используются два аргумента FileOffsetLow и FileOffsetHigh , задающие младшую и старшую части такого смещения. Аналогичным образом для задания числа байтов в блокируемом участке предназначены два аргумента nNumberOfBytesToLockLow и nNumberOfBytesToLockHigh , также задающие младшую и старшую части этого числа.

Удалось или нет заблокировать запрошенный участок, программа определяет по возвращаемому функцией LockFile логическому значению. При неудачном задании блокировки выполняемая программа не приостанавливается сама по себе, но для этого требуется выполнение дополнительных операторов, вызывающих системные функции, которые рассмотрим впоследствии. (Простейшим, но не эффективным решением являются многократные попытки успешно выполнить функцию блокировки LockFile до тех пор, пока она не вернет значение, свидетельствующее о успешно установленной блокировке.)

Обратной к функции LockFile является системная функция UnlockFile, которая имеет прототип

BOOL UnlockFile(HANDLE hFile,

DWORD FileOffsetLow, DWORD FileOffsetHigh,

DWORD cbUnlockLow, DWORD cbUnlockHigh),

где аргументы по своему назначению совпадают с уже рассмотренными в функции LockFile. Данная функция снимает блокировку с указанного в ней участка, давая тем самым свободный доступ к нему, если это, конечно, согласуется с общими режимами доступа для других процессов, определяемыми аргументом ShareMode в функции открытия файла CreateFile.

Кроме двух рассмотренных функций, предназначенных для управления блокировкой отдельных участков в Windows, эта ОС содержит несколько позже добавленные в нее функции, которые дают возможности расширенного управления выборочной блокировкой. Это – функции LockFileEx и UnlockFileEx, которые имеют прототипы

BOOL LockFileEx(HANDLE hFile, DWORD Flags,

DWORD dwReserved,

DWORD nNumberOfBytesToLockLow,

DWORD nNumberOfBytesToLockHigh,

LPOVERLAPPED lpOverlapped)

BOOL UnlockFileEx(HANDLE hFile, DWORD dwReserved,

DWORD nNumberOfBytesToUnlockLow,

DWORD nNumberOfBytesToUnlockHigh,

LPOVERLAPPED lpOverlapped).

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

LOCKFILE_FAIL_IMMEDIATELY

LOCKFILE_EXCLUSIVE_LOCK

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

В двух последних функциях значение смещения рассматриваемого участка файла размещается внутри структуры данных, задаваемых последним аргументом. Как видим, полноценное блокирование участков файлов в ОС типа Windows задается в действительности еще сложней чем в Unix.

Разделы на этой странице:

В системах, допускающих одновременное выполнение нескольких процессов, особую актуальность приобретает проблема координации и синхронизации доступа к разделяемым (совместно используемым) объектам, например файлам.

В Windows имеется возможность блокировать файлы (целиком или частично) таким образом, что никакой другой процесс (выполняющаяся программа) не сможет получить доступ к заблокированному участку файла. Блокирование файла может оставлять другим приложениям возможность доступа только для чтения (разделяемый доступ) или же закрывать им доступ к файлу как для записи, так и для чтения (монопольный доступ). Что немаловажно, владельцем блокировки является блокирующий процесс. Любая попытка получения доступа к части файла (с помощью функций ReadFile или WriteFile) в нарушение существующей блокировки закончится неудачей, поскольку блокировки носят обязательный характер на уровне процесса. Любая попытка получения несовместимой блокировки также завершится неудачей, даже если процесс уже владеет данной блокировкой. Блокирование файлов является ограниченной разновидностью синхронизации параллельно выполняющихся процессов и потоков; обсуждение синхронизации с использованием гораздо более общей терминологии начнется в главе 8.

Для блокирования файлов предусмотрены две функции. Более общей из них является функция LockFileEx, менее общей - LockFile, которую можно использовать и в Windows 9x.

Функция LockFileEx относится к классу функций расширенного (extended) ввода/вывода, поэтому для указания 64-битовой позиции в файле и границ области файла, подлежащей блокированию, необходимо использовать структуру OVERLAPPED, которая ранее уже применялась при указании позиции в файле для функций ReadFile и WriteFile.

BOOL LockFileEx(HANDLE hFile, DWORD dwFlags, DWORD dwReserved, DWORD nNumberOfBytesToLockLow, DWORD nNumberOfBytesToLockHigh, LPOVERLAPPED lpOverlapped)

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

Параметры

hFile - дескриптор открытого файла. Дескриптор должен быть создан либо с правами доступа GENERIC_READ, либо с правами доступа GENERIC_READ и GENERIC_WRITE.

dwFlags - определяет вид блокировки файла, а также режим ожидания доступности затребованной блокировки. Этот параметр определяется комбинацией следующих значений:

LOCKFILE_EXCLUSIVE_LOCK - запрос монопольной блокировки в режиме чтения/записи. Если это значение не задано, запрашивается разделяемая блокировка (только чтение).

LOCKFILE_FAIL_IMMEDIATELY - задает режим немедленного возврата функции с возвращаемым значением равным FALSE, если приобрести блокировку не удается. Если это значение не задано, функция переходит в режим ожидания.

dwReserved - значение этого параметра должно устанавливаться равным 0. Следующие два параметра определяют соответственно младшие и старшие 32-битовые значения размера блокируемого участка файла (в байтах).

lpOverlapped - указатель на структуру данных OVERLAPPED, содержащую информацию о начале блокируемого участка. В этой структуре необходимо устанавливать значения трех элементов (остальные элементы игнорируются), первые два из которых определяют смещение начала блокируемого участка от начала файла.

DWORD Offset (используется именно такое имя параметра, а не OffsetLow).

DWORD OffsetHigh.

HANDLE hEvent должен задаваться равным 0.

Чтобы разблокировать файл, следует вызвать функцию UnlockFileEx, все параметры которой, за исключением dwFlags, совпадают с параметрами предыдущей функции:

BOOL UnlockFileEx(HANDLE hFile, DWORD dwReserved, DWORD nNumberOfBytesToLockLow, DWORD nNumberOfBytesToLockHigh, LPOVERLAPPED lpOverlapped)

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

Границы области разблокирования должны в точности совпадать с границами ранее заблокированной области. Не допускается, например, объединение двух ранее заблокированных областей или разблокирование части заблокированной области. Любая попытка разблокирования области, не совпадающей в точности с одной из существующих заблокированных областей, будет неудачной. В этом случае функция вернет значение FALSE, а в выведенном системой сообщении об ошибке будет указано, что данная область блокирования не существует.

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

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

Блокировки не наследуются вновь создаваемыми процессами.

Логику процедуры блокирования, когда вся область или только некоторая ее часть уже содержат заблокированные участки, иллюстрирует табл. 3.1.

Таблица 3.1. Логика предоставления блокировки

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

Таблица 3.2. Блокировки и выполнение операций ввода/вывода

Операция ввода/вывода Существующая блокировка Чтение Запись
Отсутствует Успешно выполняется Успешно выполняется
Разделяемая блокировка (одна или несколько) Выполняется. Вызывающий процесс не обязан быть владельцем блокировки данной области файла. Не выполняется
Монопольная блокировка Выполняется, если вызывающий процесс является владельцем блокировки, в противном случае - неудачное завершение.

Обычно операции чтения и записи выполняются путем вызова функций Read-File и WriteFile или их расширенных версий ReadFileEx и WriteFileEx. Для диагностики ошибок, возникающих в процессе выполнения операций ввода/вывода, следует вызывать функцию GetLastError.

Одна из разновидностей операций ввода/вывода с участием файлов предполагает использование отображения файлов, которое обсуждается в главе 5. Обнаружение конфликтов блокировки на этапе обращения к памяти не производится; такая проверка осуществляется во время вызова функции MapViewOfFile. Указанная функция делает часть файла доступной для процесса, вследствие чего проверка наличия блокировок на этом этапе является необходимой.

Итак, начнем с того, что же такое исключительная блокировка файла и для чего она необходима. Не секрет, что множество сайтов хранят свою информацию не в базах данных, а в простых тестовых файлах. Здесь мы не будем спорить, что лучше и хуже, мы просто поговорим о специфике работы с данными, хранящимися в файлах. Эти данные могут иметь различные форматы, различные структуры, но так или иначе манипуляцию этими данными мы должны взять на себя. Нужно четко понимать, что это бывает иногда сложней, чем кажется на первый взгляд. Действительно, когда Вы тестируете свои скрипты, все кажется идеальным: информация добавляется, информация удаляется… Но стоит только начать работу в сети и ситуация может кардинально измениться. В ситуации, когда со скриптом работает одновременно большое количество людей очень важно не потерять контроль над операциями работы с файлом. Возможны ситуации, когда двое или более людей одновременно запросят операции записи в файл и произойдет серьезный сбой, который повлечет потерю информации. Модель исключительной блокировки предотвращает подобные ситуации, "разруливая" процессы, работающие с файлом и не давая им одновременно выполнять опасные операции.

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

Здесь мы открыли файл в режиме добавления информации в конец файла, записали в него порцию информации $data и затем закрыли его (Предполагается, что у нас есть права на запись в файл). Это самое простое и самое первое, что нам могло прийти в голову и что мы реализовали. Если вы уверены, что никаких проблем с файлом не возникнет или что у вас не так много посетителей, чтобы что-то сломалось, то это ваше право — можете закрыть статью и жить спокойно! 😉 Но нужно что-то делать. Одним из примеров трагедий может служить сайт http://manlix.ru, в котором постоянно "падает" форум и/или счетчик посетителей. Я, конечно, не берусь судить, что только некорректная работа с файлами тому виной, но, по-моему, это очевидно. Пока число посетителей было сравнительно небольшим, все корректно функционировало, как только иногда одновременно стало появляться до 10 пользователей одновременно, начались казусы с счетчиком и форумом. Как же это преодолеть? Оказывается просто, всего лишь добавив несколько строк в операцию работы с файлами:

В данном примере мы открыли файл для добавления в него информации Предполагается, что у нас есть права на запись в файл). Затем применили исключительную блокировку и тем самым сделали наш скрипт единственным процессом, который в текущий момент имеет доступ к файлу. Блокировка действительна все время от выполнения функции flock ($fp,LOCK_EX) и до выполнения flock ($fp,LOCK_UN). Между этими функциями находятся операторы, выполнение которых будет "безопасным" для файла. Другие процессы смогут получить доступ к файлу не раньше снятия блокировки. Важным моментом является применение функции fflush ($fp). Транзакции изменения данных могут быть записаны с специальный файловый буфер и сброшены на диск позже, когда блокировка будет уже снята и снова будет опасность сбоя в работе. Поэтому данной функцией мы принудительно записываем изменения на диск, сбрасывая содержимое буфера. Еще одним не менее важным моментом является, само открытие файла! Мы не случайно используем режим "a" ("a+"). Если нам будет необходима запись в начало файла с удалением предыдущего содержимого, то следует воздержаться от применения режима "w" ("w+"), поскольку очищение файла предполагает удаление не только содержимого, но и самого файла с последующим созданием аналогичного. Так как этот процесс будет выполнен до исключительной блокировки, то также существует вероятность сбоя в работе. В данном случае стоит применять следующий прием:

Здесь мы открыли файл для записи в него, затем применили исключительную блокировку, и только уж потом применили функцию ftruncate ($fp,0) которая выполнила так необходимую нам очистку файла от содержимого. Вот вроде бы и все, что я хотел вам для начала рассказать! Успехов Вам в нашем нелегком труде! До новых встреч, до новых статей!

Хорошо Плохо



Рекомендуем почитать

Наверх