Обеспечить контроль над открытым файлом
#include <sys/types.h>#include <unistd.h>#include <fcntl.h>int fcntl( int fildes,int cmd,... );
libc
Функция fcntl() предоставляет управление над открытым файлом, связанным с файловым дескриптором fildes. Чтобы установить блокировку с помощью этой функции, необходимо открыть файл с правом только на запись ( O_WRONLY) или на чтение/запись ( O_RDWR).
Тип управления определяется аргументом cmd, который может требовать третий аргумент данных (arg). Аргумент cmd определен в <fcntl.h>
и включает минимум следующие значения:
F_ALLOCSP
за исключением того, что аргумент указывает на структуру struct flock64, где поля l_start и l_len являются 64
-битными значениями. int
. Новый файловый дескриптор ссылается на тот же файл, что и fildes, и разделяет те же блокировки. F_FREESP
за исключением того, что аргумент указывает на структуру struct flock64, где поля l_start и l_len являются 64
-битными значениями. <fcntl.h>
. F_GETLK
за исключением того, что аргумент указывает на структуру struct flock64, где поля l_start и l_len являются 64
-битными значениями. int
. Смотрите обсуждение выше для дополнительной информации. Определены следующие флаги файлового дескриптора: int
. Эту функцию можно применять для изменения режима доступа к файлу. Все биты из arg, отличные от битов статуса файла, игнорируются. <fcntl.h>
): F_SETLK
за исключением того, что аргумент указывает на структуру struct flock64, где поля l_start и l_len являются 64
-биитными значениями. -1
с установкой errno в EINTR
. F_GETLKW
за исключением того, что аргумент указывает на структуру struct flock64, где поля l_start и l_len являются 64
-битными значениями. Когда разделяемая блокировка устанавливается для сегмента файла, другие процессы могут также установить разделяемую блокировку на тот же сегмент или его часть. Разделяемаая блокировка не дает другим процессам установить эксклюзивную блокировку на любую часть защищенной области. Запрос на разделяемую блокировку завершается неудачно, если файл открыт только для записи.
Эксклюзивная блокировка не дает другим процессам установить эксклюзивную или разделяемую блокировку на любую часть защищенной области. Запрос на эксклюзивную блокировку завершается неудачно, если файл открыт только для чтения.
Блокировки могут начинаться и выходить за пределы конца файла, но не могут начинаться и выходить за пределы начала файла, попытка сделать подобное приведет к ошибке. Блокировка распространяется на “бесконечность” (максимально возможное значение для смещения файла), если l_len установлено в ноль. Если l_whence и l_start указывают на начало файла, и l_len равно нулю, блокируется весь файл.
Вызывающий процесс может иметь только один тип блокировки для каждого байта файла. Перед успешным возвратом из запроса F_SETLK или F_SETLKW предыдущий тип блокировки (если есть) для каждого байта в указанной области блокировки меняется на новый тип блокировки. Все блокировки для данного процесса, связанные с файлом, снимаются, когда файловый дескриптор файла закрывается процессом или процесс, содержащий файловый дескриптор, завершается. Блокировки не наследуются дочерними процессами, созданными функцией fork(). Однако блокировки наследуются через вызовы exec*() или spawn*().
Потенциальная взаимоблокировка возможна, если процесс, управляющий заблокированной областью, переводится в спящий режим, пытаясь блокировать заблокированную область. Если система определяет, что спящий режим при попытке блокировки приведет к взаимоблокировке, fcntl() завершится с EDEADLK . Однако система не всегда может обнаруживать подобные взаимоблокировки в случае работы по сети, поэтому это следует учитывать при разработке приложения. |
Блокировка - протокол, разработанный для обновления файла, совместно используемого запущенными приложениями. Блокировки носят рекомендательный характер, то есть не препятствуют ошибочному или плохо спроектированному приложению перезаписать заблокированную область разделяемого файла. Приложение должно использовать блокировки для указания области файла, которая должна быть обновлена, также оно должно учитывать блокировки других приложений.
Следующие функции игнорируют блокировку: |
Если возникла ошибка, функция возвращает -1
, код ошибки записывается в errno. При успешном завершении возвращаемое значение зависит от arg:
F_DUPFD
— Новый файловый дескриптор. F_GETFD
— Значение флагов файлового дескриптора (не может быть отрицательным). F_GETFL
— Значение флагов статуса файла и режима доступа, как показано выше (не может быть отрицательным). F_GETLK
— Значение, отличное от -1
. F_SETFD
— Значение, отличное от -1
. F_SETFL
— Значение, отличное от -1
. F_SETLK
— Значение, отличное от -1
. F_SETLKW
— Значение, отличное от -1
.
/** This program makes "stdout" synchronous* to guarantee the data is recoverable* (if it's redirected to a file).*/#include <unistd.h>#include <fcntl.h>#include <stdio.h>#include <stdlib.h>int main( void ){int flags, retval;flags = fcntl( STDOUT_FILENO, F_GETFL );flags |= O_DSYNC;retval = fcntl( STDOUT_FILENO, F_SETFL, flags );if ( retval == -1 ){printf( "error setting stdout flags\n" );return (EXIT_FAILURE);}printf( "hello world\n" );return (EXIT_SUCCESS);}
POSIX 1003.1
Функция fcntl() может являться точкой остановки потока в случае F_DUPFD (при дублировании по сети), F_GETFD и F_SETFD.
struct flock, struct flock64, close(), dup(), dup2(), execl(), execle(), execlp(), execlpe(), execv(), execve(), execvp(), execvpe(), ioctl(), open()
Предыдущий раздел: Описание API системной библиотеки