C linux struct flock

C linux struct flock

Функции блокирования можно использовать в следующих режимах:


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

struct flock flptr;


F_SETLK. С помощью этого режима организуется блокировка. Если блокирование невозможно, функция fcntl завершается и устанавливает переменную errno в значение EACCES или EAGAIN . С помощью F_SETLK можно также удалить установленную блокировку ( F_UNLCK ):

if((fcntl(fd, F_SETLK, &flptr)!=-1)

if((fcntl(fd, F_SETLK, &sperre)!=-1)

if((fcntl(fd, F_SETLK, &flptr)!=-1)


F_SETLKW. С помощью этого режима процесс приостанавливается до тех пор, пока не реализует необходимую блокировку.


Если для файла нужно предусмотреть блокировку записи ( F_WRLCK ), то файл должен быть открыт для записи ( O_WRONLY ). Таким же образом, если необходима блокировка чтения ( F_RDLCK ), то файл открывается в режиме чтения ( O_RDONLY ). Это означает также, что блокировки не должны одновременно устанавливаться на определенный байт.

Пример, иллюстрирующий режимы блокировки:

#define FNAME «locki.lck»

void status(struct flock *lock)

printf(«F_UNLCK (Блокировка снята)\n»);

printf(«F_RDLCK (pid: %d)

printf(«F_WRLCK (pid: %d)

int main(int argc, char **argv)

struct flock lock;

fd = open(FNAME, O_WRONLY|O_CREAT|O_APPEND,

/*Проверим, установлена ли блокировка*/

if (fcntl(fd, F_SETLK, &lock) 1)

if (fcntl(fd, F_SETLK, &lock)

Этот пример иллюстрирует возможности сериализации процессов. Тем не менее здесь все равно возможны чтение и запись в процессе-потомке. Такой вариант блокировки называется advisory locking (необязательная блокировка). При его установке не производится никаких дополнительных проверок того, должны ли системные функции open , read и write из-за блокировки запрещаться при вызове. Для advisory locking принимается, что пользователь сам является ответственным за проверку того, существуют ли определенные блокировки или нет. Невозможно запретить всем процессам доступ к файлу. Только процессы, опрашивающие наличие блокировки с помощью fcntl , блокируются при ее наличии (и то не всегда).

Для других случаев имеются так называемые строгие блокировки (mandatory locking). Эти блокировки запрещают процессу получать доступ с помощью функций read или write к данным, которые ранее были блокированы другим процессом через fcntl .

Строгие блокировки можно разрешить, установив бит Set-Group-ID и сняв бит выполнения для группы, например:

int mandatory_lock(int fd)

struct stat statbuffer;

if(fstat(fd, &statbuffer) Строгая блокировка является зависимой от системы. Однако, она не может предотвратить удаление файла через unlink ().

Если с помощью open () открывается файл с флагами O_TRUNC и O_CREAT и для этого файла установлена строгая блокировка, то возвращается ошибка со значением errno=EAGAIN .

Next: Блокировка частей файла и Up: Блокировка файлов Previous: Структура flock Contents 2004-06-22

Источник

C linux struct flock

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

Однако, данные два дескриптора не разделяют флаг close-on-exec. Флаг close-on-exec в копии выключен. Это означает, что дескриптор не будет закрыт в случае вызова exec.

При успешном выполнении этой операции, возвращается новый файловый дескриптор. F_GETFD Читает флаг close-on-exec. Если бит FD_CLOEXEC установлен в 0, то файл будет оставлен открытым при вызове exec , в противном случае он будет закрыт. F_SETFD Устанавливает флаг close-on-exec в значение, заданное битом FD_CLOEXEC аргумента arg .

Флаги состояния файла

Эти флаги и их смысл описываются на странице руководства open (2). F_GETFL Читает флаги файлового дескриптора. F_SETFL Устанавливает часть флагов, относящихся к состоянию файла, согласно значению, указанному в аргументе arg . Оставшиеся биты (режим доступа, флаги создания файла) в значении arg игнорируются. В Linux данная команда может изменять только флаги O_APPEND, O_NONBLOCK, O_ASYNC и O_DIRECT.

Совместная (advisory) блокировка


Обязательная (mandatory) блокировка

Совместные блокировки не являются принудительными и полезны только между сотрудничающими процессами. Обязательные блокировки являются принудительными для всех процессов.

Управление сигналами

Если вы установили на файловый дескриптор флаг состояния O_ASYNC (или через предоставление этого флага в вызове open (2), или используя команду F_SETFL вызова fcntl ), то сигнал SIGIO посылается всякий раз, когда для данного файлового дескриптора становится возможным ввод или вывод.

Процесс или группа процесса, для приёма сигнала могут быть выбраны, используя команду F_SETOWN в вызове fcntl . Если файловым дескриптором является сокет, то для него также выбирается получатель сигналов SIGURG, которые доставляются, когда на сокет поступает данных больше, чем его пропускная способность. (SIGURG посылается во всех ситуациях, когда вызов select (2) говорит, что сокет находится в состоянии «исключительной ситуации»). Если файловый дескриптор соответствует терминальному устройству, то группе процессов, которые работают с терминалом не в фоновом режиме будут посылаться сигналы SIGIO. F_GETSIG Получить сигнал, который будет послан, когда станет возможен ввод или вывод. Значение 0 означает сигнал SIGIO. Любое другое значение (включая SIGIO) является другим сигналам, посылаемым вместо SIGIO и в это случае, для обработчика сигнала доступна дополнительная информация, если он был установлен с SA_SIGINFO. F_SETSIG Установить сигнал, который будет послан, когда станет возможен ввод или вывол. Значение 0 означает сигнал SIGIO. Любое другое значение (включая SIGIO) является другим сигналам, посылаемым вместо SIGIO и в это случае, для обработчика сигнала доступна дополнительная информация, если он был установлен с SA_SIGINFO.

В случае использования F_SETSIG с ненулевым значением и установкой SA_SIGINFO для обработчика сигнала (см. sigaction (2)), обработчику передаётся дополнительная информация о событиях ввода/вывода в структуре siginfo_t . Если поле si_code показывает, что сигналом является SI_SIGIO, то поле si_fd содержит файловый дескриптор, ассоциированный с собрытием вывода/вывода. В противном случае, не существует никакого механизма, чтобы сообщить с каким файловым дескриптором связан полученный сигнал и вы должны использовать ( select (2), poll (2), read (2) с установленным флагом O_NONBLOCK и т.д.) чтобы определить какой файловый дескриптор доступен для ввода/вывода.

При выборе сигнала реального времени (value >= SIGRTMIN) как описано в POSIX.1b, в очередь будут добавляться несколько событий ввода вывода, с теми же номерами сигналов. (Размер очереди зависит от доступной памяти). Дополнительная информация будет доступна как описано выше, если для обработчика сигнала будет установлено SA_SIGINFO.

Используя эти механизмы, программа может реализовать полностью асинхронный ввода/вывод без использования в своей работе select (2) или poll (2).

Использование O_ASYNC , F_GETOWN , F_SETOWN является специфичным для BSD и Linux. F_GETSIG и F_SETSIG являются специфичными для Linux. POSIX описывает асинхронный ввод/вывод и структуру aio_sigevent используемую для сходных вещей; которые также доступны в Linux как часть библиотеки GNU C (Glibc).

Аренда

F_RDLCK Установить аренду чтения. Это приведёт к генерации уведомления, когда другой процесс открывает указанный файл для записи или усекает его. F_WRLCK Установить аренду записи. Это приведёт к генерации уведомления, когда другой процесс открывает указанный файл (для чтения или записи) или усекает его. Аренда записи может быть установлена на файл, только если этот файл не открыт в этот момент каким-либо другим процессом. F_UNLCK Удалить аренду с указанного файла. Процесс может удержитвать для файла только один тип аренды. Аренда может быть установлена только для обычных файлов. Непривелегированный процесс может установить аренту только для файла, у которого UID совпадает с UID файловой системы этого процесса. F_GETLEASE Показывает какой тип аренды удерживается для файла, на который указывает fd и возвращает одно из значений F_RDLCK , F_WRLCK или F_UNLCK, соответственно показывающих, что вызывающий процесс удерживает аренду чтения, записи или что аренды нет. (Третий аргумент fcntl () при этому опускается.)

Когда конкурент выполняет вызов open () или truncate (), который конфликтует с арендой, установленной через F_SETLEASE , системный вызов блокируется ядром (за исключением случая, когда при вызове open () указывается флаг O_NONBLOCK ; в этом случае немедленно возращается ошибка EWOULDBLOCK ). Затем ядро уведомляет держателя аренды, отправляя ему сигнал (по умолчанию SIGIO). Держатель аренты должен при получении этого сигнала выполнить все необходимые действия для подготовки этого файла к использованию другим процессом (например, сбросить буферы кэша) и затем удалить аренду, выполнив операцию F_SETLEASE и установив значение аргумента arg в F_UNLCK .

Если держатель аренды не освободит аренду в течении количества секунд, которое задаётся в файле /proc/sys/fs/lease-break-time , а системный вызов конкурента останется блокирующим (то, есть конкурент не установит флаг O_NONBLOCK для системного вызова open () и этот системный вызов не будет прерван обработчиком события), то ядро принудительно удалит аренду у процесса держателя аренды.

После того как аренда снята держателем аренды или принудительно удалена ядром, ядро снимает блокировку с системного вызова процесса конкуренту и разрешает продолжить его работу.

По умолчанию, для уведомления держателя аренды используется сигнал SIGIO, но его можно изменить, используя команду F_SETSIG для fcntl (). Если выполняется команда F_SETSIG (даже назначая сигнал SIGIO) и при этом обработчик сигнала устанавливается с использованием SA_SIGINFO, то обработчик будет получит в качестве второго аргумента структуру siginfo_t , в которой поле si_fd будет содержать дескриптор файла, для которого установлена аренда и которому пытается получить доступ другой процесс. (Это полезно, если вызывающий процесс удерживает аренду на несколько файлов).

Уведомления об изменении файла и каталога

Маска Описание (событие в каталоге)
DN_ACCESS
DN_MODIFY Файл был изменён (write, pwrite,
writev, truncate, ftruncate)
DN_CREATE Файл был создан (open, creat, mknod,
mkdir, link, symlink, rename)
DN_DELETE Файл был удалён (unlink, rename в
другой каталог, rmdir)
DN_RENAME Файл был переименован внутри каталога (rename)
DN_ATTRIB У файла был изменён атрибут (chown, chmod, utime[s])

(Чтобы включить определения этих масок, нужно задать макроопределение _GNU_SOURCE до подключения .)

Уведомления об изменении состояния каталога обычно однократные и приложение должно перерегистрировать установку уведомлений, чтобы и дальше получать их. Однако, если в аргумент arg добавить маску DN_MULTISHOT , то уведомления будут происходить до тех пор, пока не будут явно отменены.

Серии запросов F_NOTIFY накапливаются, таким образом запросы на уведомления, указываемые в arg будут добавляться к тем, что уже установлены. Чтобы запретить уведомления для всех событий, выполните вызов F_NOTIFY , в котором значение arg установлено в 0.

Уведомления выполняются через доставку сигнала. По умолчанию — это SIGIO, но вы можете изменить его, используя команду F_SETSIG для вызова fcntl (). В последнем случае, обработчик сигнала получит в качестве второго аргумента структуру siginfo_t (если обработчик был установлен с использованием SA_SIGINFO), а поле si_fd в этой структуре будет содержать дескриптор файла, для которого было сегенерировано уведомление (полезно, когда устанавливается уведомление для нескольких каталогов).

Кроме того, когда используется DN_MULTISHOT , для уведомлений должен бы быть использован сигнал реального времени POSIX.1b, так что множественные уведомления могут быть поставлены в очередь.

ВОЗВРАЩАЕМОЕ ЗНАЧЕНИЕ

В случае ошибки, возвращается -1 и значение errno устанавливается соответствующим образом.

ОШИБКИ


ЗАМЕЧАНИЯ

Начиная с ядра 2.0, не существует разницы между типами блокировки, которые осуществляет flock (2) и fcntl (2).

POSIX 1003.1-2001 разрешает отрицательное значение l_len . (И если оно отрицательное, интервал, описывающий блокировку покрывает l_start + l_len байт, включая l_start -1.) Это поддерживатся, начиная с Linux 2.4.21 и 2.5.49.

Некоторые системы имеют больше полей в структуре struct flock например такие как l_sysid . Вообще-то, один l_pid не очень-то полезен, если процесс, удерживающий блокировку может работать на другой машине.

СООТВЕТСТВИЕ СТАНДАРТАМ

SVr4 документирует дополнительные условия ошибок EIO, ENOLINK и EOVERFLOW.

Источник

C linux struct flock

This section describes record locks that are associated with the process. There is also a different type of record lock that is associated with the open file description instead of the process. See Open File Description Locks.

The remaining fcntl commands are used to support record locking, which permits multiple cooperating programs to prevent each other from simultaneously accessing parts of a file in error-prone ways.

An exclusive or write lock gives a process exclusive access for writing to the specified part of the file. While a write lock is in place, no other process can lock that part of the file.

A shared or read lock prohibits any other process from requesting a write lock on the specified part of the file. However, other processes can request read locks.

The read and write functions do not actually check to see whether there are any locks in place. If you want to implement a locking protocol for a file shared by multiple processes, your application must do explicit fcntl calls to request and clear locks at the appropriate points.

Locks are associated with processes. A process can only have one kind of lock set for each byte of a given file. When any file descriptor for that file is closed by the process, all of the locks that process holds on that file are released, even if the locks were made using other descriptors that remain open. Likewise, locks are released when a process exits, and are not inherited by child processes created using fork (see Creating a Process).

When making a lock, use a struct flock to specify what kind of lock and where. This data type and the associated macros for the fcntl function are declared in the header file fcntl.h .

Data Type: struct flock

This structure is used with the fcntl function to describe a file lock. It has these members:

short int l_type

Specifies the type of the lock; one of F_RDLCK , F_WRLCK , or F_UNLCK .

short int l_whence

This corresponds to the whence argument to fseek or lseek , and specifies what the offset is relative to. Its value can be one of SEEK_SET , SEEK_CUR , or SEEK_END .

This specifies the offset of the start of the region to which the lock applies, and is given in bytes relative to the point specified by the l_whence member.

This specifies the length of the region to be locked. A value of 0 is treated specially; it means the region extends to the end of the file.

This field is the process ID (see Process Creation Concepts) of the process holding the lock. It is filled in by calling fcntl with the F_GETLK command, but is ignored when making a lock. If the conflicting lock is an open file description lock (see Open File Description Locks), then this field will be set to -1.

Macro: int F_GETLK

This macro is used as the command argument to fcntl , to specify that it should get information about a lock. This command requires a third argument of type struct flock * to be passed to fcntl , so that the form of the call is:

If there is a lock already in place that would block the lock described by the lockp argument, information about that lock overwrites * lockp . Existing locks are not reported if they are compatible with making a new lock as specified. Thus, you should specify a lock type of F_WRLCK if you want to find out about both read and write locks, or F_RDLCK if you want to find out about write locks only.

There might be more than one lock affecting the region specified by the lockp argument, but fcntl only returns information about one of them. The l_whence member of the lockp structure is set to SEEK_SET and the l_start and l_len fields set to identify the locked region.

If no lock applies, the only change to the lockp structure is to update the l_type to a value of F_UNLCK .

The normal return value from fcntl with this command is an unspecified value other than -1, which is reserved to indicate an error. The following errno error conditions are defined for this command:

The filedes argument is invalid.

Either the lockp argument doesn’t specify valid lock information, or the file associated with filedes doesn’t support locks.

Macro: int F_SETLK

This macro is used as the command argument to fcntl , to specify that it should set or clear a lock. This command requires a third argument of type struct flock * to be passed to fcntl , so that the form of the call is:

If the process already has a lock on any part of the region, the old lock on that part is replaced with the new lock. You can remove a lock by specifying a lock type of F_UNLCK .

If the lock cannot be set, fcntl returns immediately with a value of -1. This function does not block while waiting for other processes to release locks. If fcntl succeeds, it returns a value other than -1.

The following errno error conditions are defined for this function:

The lock cannot be set because it is blocked by an existing lock on the file. Some systems use EAGAIN in this case, and other systems use EACCES ; your program should treat them alike, after F_SETLK . (GNU/Linux and GNU/Hurd systems always use EAGAIN .)

Either: the filedes argument is invalid; you requested a read lock but the filedes is not open for read access; or, you requested a write lock but the filedes is not open for write access.

Either the lockp argument doesn’t specify valid lock information, or the file associated with filedes doesn’t support locks.

The system has run out of file lock resources; there are already too many file locks in place.

Well-designed file systems never report this error, because they have no limitation on the number of locks. However, you must still take account of the possibility of this error, as it could result from network access to a file system on another machine.

Macro: int F_SETLKW

This macro is used as the command argument to fcntl , to specify that it should set or clear a lock. It is just like the F_SETLK command, but causes the process to block (or wait) until the request can be specified.

This command requires a third argument of type struct flock * , as for the F_SETLK command.

The fcntl return values and errors are the same as for the F_SETLK command, but these additional errno error conditions are defined for this command:

The function was interrupted by a signal while it was waiting. See Interrupted Primitives.

The specified region is being locked by another process. But that process is waiting to lock a region which the current process has locked, so waiting for the lock would result in deadlock. The system does not guarantee that it will detect all such conditions, but it lets you know if it notices one.

The following macros are defined for use as values for the l_type member of the flock structure. The values are integer constants.

This macro is used to specify a read (or shared) lock.

This macro is used to specify a write (or exclusive) lock.

This macro is used to specify that the region is unlocked.

As an example of a situation where file locking is useful, consider a program that can be run simultaneously by several different users, that logs status information to a common file. One example of such a program might be a game that uses a file to keep track of high scores. Another example might be a program that records usage or accounting information for billing purposes.

Having multiple copies of the program simultaneously writing to the file could cause the contents of the file to become mixed up. But you can prevent this kind of problem by setting a write lock on the file before actually writing to the file.

If the program also needs to read the file and wants to make sure that the contents of the file are in a consistent state, then it can also use a read lock. While the read lock is set, no other process can lock that part of the file for writing.

Remember that file locks are only an advisory protocol for controlling access to a file. There is still potential for access to the file by programs that don’t use the lock protocol.

Источник

Читайте также:  Nmap gui для windows
Оцените статью