fcntl()

Обеспечить контроль над открытым файлом

Прототип:

#include <sys/types.h>
#include <unistd.h>
#include <fcntl.h>
int fcntl( int fildes,
int cmd,
... );

Аргументы:

fildes
Дескриптор файла, которым необходимо управлять.
cmd
Команда для выполнения.

Библиотека:

libc

Описание:

Функция fcntl() предоставляет управление над открытым файлом, связанным с файловым дескриптором fildes. Чтобы установить блокировку с помощью этой функции, необходимо открыть файл с правом только на запись ( O_WRONLY) или на чтение/запись ( O_RDWR).

Тип управления определяется аргументом cmd, который может требовать третий аргумент данных (arg). Аргумент cmd определен в <fcntl.h> и включает минимум следующие значения:

F_ALLOCSP
Выделить место для хранения раздела файла, определенного полями l_start, l_len и l_whence структуры struct flock, на которую указывает дополнительный аргумент fcntl()
F_ALLOCSP64
Похож на F_ALLOCSP за исключением того, что аргумент указывает на структуру struct flock64, где поля l_start и l_len являются 64-битными значениями.
F_DUPFD
Выделить и вернуть новый файловый дескриптор, имеющий наименьшее доступное (то есть все еще не открытый) значение, равное или превышающее третий аргумент arg, взятый как int. Новый файловый дескриптор ссылается на тот же файл, что и fildes, и разделяет те же блокировки.
F_FREESP
Освободить место для хранения раздела файла, определенного полями l_start, l_len и l_whence структуры struct flock, на которую указывает дополнительный аргумент fcntl().
F_FREESP64
Похож на F_FREESP за исключением того, что аргумент указывает на структуру struct flock64, где поля l_start и l_len являются 64-битными значениями.
F_GETFD
Получить флаги файлового дескриптора fildes. Флаги файлового дескриптора связаны с конкретным файловым дескриптором и не зависят от файловых дескрипторов, указывающих на тот же файл.
F_GETFL
Получить флаги статуса файла и режимы доступа, связанные с fildes. Флаги и режимы определены в <fcntl.h>.

Флаги статуса файла (смотрите open() для более детальной информации): Режимы доступа файла:
F_GETLK
Получить первую блокировку, препятствующую создать блокировку с описанием, на которое указывает третий аргумент arg, передаваемый как указатель на тип struct flock. Возвращенная информация перезаписывает информацию, переданную в fcntl() в структуре, на которую указывает arg.

Если не найдено блокировок, препятствующих созданию блокировки, структура остается неизменной, за исключением типа блокировки, который устанавливается в F_UNLCK. Если блокировка обнаружена, поле l_pid структуры, на которую указывает arg, устанавливается в идентификатор процесса, который удерживает блокировку, и l_whence устанавливается в SEEK_SET.
F_GETLK64
Похож на F_GETLK за исключением того, что аргумент указывает на структуру struct flock64, где поля l_start и l_len являются 64-битными значениями.
F_SETFD
Установить флаги файлового дескриптора, связанного с fildes, в значение, равное третьему аргументу arg, передаваемому как int. Смотрите обсуждение выше для дополнительной информации. Определены следующие флаги файлового дескриптора:
FD_CLOEXEC
Если этот флаг сброшен, файл остается открытым при вызовах spawn*() или exec*(); в ином случае файл закрывается.
F_SETFL
Установить флаги статуса файла, как показано выше, для открытого файлового дескриптора, связанного с fildes, из соответствующих битов третьего аргумента arg, передаваемого как тип int. Эту функцию можно применять для изменения режима доступа к файлу. Все биты из arg, отличные от битов статуса файла, игнорируются.
F_SETLK
Установить или снять блокировку сегмента файла в соответствии с описанием блокировки, на которое указывает третий аргумент arg, передаваемый как указатель на тип struct flock. Эта команда используется для создания следующих блокировок (определены в <fcntl.h>):
F_RDLCK
Разделяемая блокировка или блокировка чтения.
F_UNLCK
Удаление любого типа блокировки.
F_WRLCK
Эксклюзивная блокировка или блокировка записи.
Если блокировка не может быть установлена, fcntl() немедленно завершается.
F_SETLK64
Похож на F_SETLK за исключением того, что аргумент указывает на структуру struct flock64, где поля l_start и l_len являются 64-биитными значениями.
F_SETLKW
Данная команда похожа на F_SETLK за исключением того, что когда блокировка не может выполниться из-за других блокировок, процесс ожидает, пока запрос не будет удовлетворен. Если приходит отбрабатываемый сигнал во время того, как fcntl() ожидает, вызов прерывается без выполнения операции блокировки, fcntl() возвращает -1 с установкой errno в EINTR.
F_SETLKW64
Похож на F_GETLKW за исключением того, что аргумент указывает на структуру struct flock64, где поля l_start и l_len являются 64-битными значениями.

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

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

Блокировки могут начинаться и выходить за пределы конца файла, но не могут начинаться и выходить за пределы начала файла, попытка сделать подобное приведет к ошибке. Блокировка распространяется на “бесконечность” (максимально возможное значение для смещения файла), если l_len установлено в ноль. Если l_whence и l_start указывают на начало файла, и l_len равно нулю, блокируется весь файл.

Вызывающий процесс может иметь только один тип блокировки для каждого байта файла. Перед успешным возвратом из запроса F_SETLK или F_SETLKW предыдущий тип блокировки (если есть) для каждого байта в указанной области блокировки меняется на новый тип блокировки. Все блокировки для данного процесса, связанные с файлом, снимаются, когда файловый дескриптор файла закрывается процессом или процесс, содержащий файловый дескриптор, завершается. Блокировки не наследуются дочерними процессами, созданными функцией fork(). Однако блокировки наследуются через вызовы exec*() или spawn*().


Note: Потенциальная взаимоблокировка возможна, если процесс, управляющий заблокированной областью, переводится в спящий режим, пытаясь блокировать заблокированную область. Если система определяет, что спящий режим при попытке блокировки приведет к взаимоблокировке, fcntl() завершится с EDEADLK. Однако система не всегда может обнаруживать подобные взаимоблокировки в случае работы по сети, поэтому это следует учитывать при разработке приложения.


Note: Блокировка - протокол, разработанный для обновления файла, совместно используемого запущенными приложениями. Блокировки носят рекомендательный характер, то есть не препятствуют ошибочному или плохо спроектированному приложению перезаписать заблокированную область разделяемого файла. Приложение должно использовать блокировки для указания области файла, которая должна быть обновлена, также оно должно учитывать блокировки других приложений.

Следующие функции игнорируют блокировку:


Возвращаемое значение:

Если возникла ошибка, функция возвращает -1, код ошибки записывается в errno. При успешном завершении возвращаемое значение зависит от arg:

Коды ошибок:

EAGAIN
Аргумент cmd равен F_SETLK, тип блокировки(l_type) - разделяемая блокировка ( F_RDLCK), и область файла уже эксклюзивно заблокирована другим процессом, или блокировка эксклюзивная, и некоторая часть области файла заблокирована разделяемо или эксклюзивно другим процессом.
EBADF
Одна из следующих причин:
EDEADLK
Аргумент cmd равен F_SETLKW, и определена вероятность взаимоблокировки.
EINTR
Аргумент cmd равен F_SETLKW, и функция прервана сигналом.
EINVAL
Одна из следующих причин:
EMFILE
Аргумент cmd равен F_DUPFD, и процесс не имеет неиспользуемые файловые дескрипторы или нет доступных файловых дескрипторов, равных или превышающих arg.
ENOLCK
Аргумент cmd равен F_SETLK или F_SETLKW, и удовлетворение запроса блокировки или разблокировки приводит к превышению числа областей блокировки, допустимых системой.
EOVERFLOW
Одно из возвращаемых значений не может быть корректно представлено.

Примеры:

/*
* 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 системной библиотеки