Как заблокировать файлы с помощью fopen ()? - PullRequest
17 голосов
/ 27 сентября 2011

Интересно, есть ли способ заблокировать и разблокировать файл в Linux, когда я открываю файл, используя fopen (не open)?

На основе вопроса переполнения стека C fopen vs open , fopen предпочтительнее, чем open.

Как я могу реализовать свою собственную блокировку файлов (если возможно), создавая и удаляя файлы блокировки?

Ответы [ 6 ]

16 голосов
/ 28 сентября 2011

Я бы категорически не согласился с утверждением, что fopen предпочтительнее, чем open. Невозможно безопасно использовать fopen при записи файла в каталог, доступный для записи другим пользователям из-за уязвимостей / условий гонки по символическим ссылкам, поскольку опция O_EXCL отсутствует. Если вам нужно использовать stdio в системах POSIX, лучше использовать open и fdopen, а не вызывать fopen напрямую.

Теперь, что касается блокировки, это зависит от того, что вы хотите сделать. POSIX не имеет обязательной блокировки, как Windows, но если вы просто хотите убедиться, что вы работаете с новым файлом и не забиваете существующий файл или не переходите по символической ссылке, используйте опции O_EXCL и O_NOFOLLOW, в зависимости от ситуации. Если вы хотите сделать кооперативную блокировку за пределами первоначального открытия, используйте fcntl блокировки.

16 голосов
/ 27 сентября 2011

В Linux, если вам нужен дескриптор файла (например, для перехода к примитиву блокировки файлов), вы можете использовать fileno(FILE*) для его получения. После получения дескриптора файла вы можете использовать его так, как если бы он был возвращен open.

Например, вместо

int fd = open("myfile.txt", flags);
int result = flock(fd, LOCK_SH);

Вы могли бы также сделать это:

FILE* f = fopen("myfile.txt", "r");
int result = flock(fileno(f)), LOCK_SH);

Обратите внимание, что fileno определено в стандарте POSIX, но не в стандартах C или C ++.

Что касается вашего второго вопроса, на справочной странице Linux open() 1018 * есть следующее:

Решение для выполнения атомарной блокировки файлов с использованием файла блокировки заключается в создать уникальный файл в той же файловой системе (например, включив hostname and pid), используйте link (2) , чтобы сделать ссылку на файл блокировки. Если link () возвращает 0, блокировка успешна. В противном случае используйте stat (2) на уникальный файл, чтобы проверить, увеличилось ли количество ссылок до 2, в в этом случае блокировка также успешна.

5 голосов
/ 26 ноября 2015

Файлы могут быть заблокированы с помощью flock().Его синтаксис:

 #include <sys/file.h>
 #define   LOCK_SH   1    /* shared lock */
 #define   LOCK_EX   2    /* exclusive lock */
 #define   LOCK_NB   4    /* don't block when locking */
 #define   LOCK_UN   8    /* unlock */

int flock(int fd, int operation);

Первый файл открывается с помощью fopen() или open().Затем этот открытый файл блокируется с помощью flock(), как указано ниже

int fd = open("test.txt","r");
int lock = flock(fd, LOCK_SH);  // Lock the file . . .
// . . . .
// Locked file in use 
// . . . .
int release = flock(fd, LOCK_UN);  // Unlock the file . . .
1 голос
/ 28 декабря 2016

Обратите внимание, что в приведенном ниже коде fopen не удастся (и вернет NULL), если файл блокировки /var/lock/my.lock не существует.

FILE* f = fopen("/var/lock/my.lock", "r");
int result = flock(fileno(f)), LOCK_SH);

Используйте fopen с w+, если вам нужнофайл блокировки, который будет создан, если он не существует.

FILE* f = fopen("/var/lock/my.lock", "w+");
int result = flock(fileno(f)), LOCK_SH);
1 голос
/ 27 сентября 2011

Если вы хотите просто реализовать свою собственную блокировку, я предлагаю Робу ответ об использовании flock. Если вы хотите реализовать его сложным образом, например, для обеспечения высокой доступности, вы можете попробовать что-то вроде использования потока для регулярного обращения к файлу. Все другие программы, желающие заблокировать файл, должны также проверить файл, чтобы узнать, было ли обновлено время его обновления в другом фиксированном, но большем интервале (большая часть важна). Это, вероятно, излишне для большинства приложений, но обрабатывает такие вещи, как сбои, зависания и т. Д., Намного лучше, чем flock.

0 голосов
/ 28 декабря 2016

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

Код здесь:

#include <stdio.h>
#include <fcntl.h>
#include <sys/stat.h>
#include <sys/types.h>

#define FILE_NAME "hello.txt"

int main()
{
    int fd;

    fd = open(FILE_NAME, O_CREAT, S_IRWXU);

    // Error checking
    if(fd == -1){
        perror("[error]\n");
    }
    else{
        printf("[file is opened]\n");
    }

    return 0;
}

Я использовал флаг для прав доступа (третий аргумент).Этот флаг дает пользователю права на чтение, запись и выполнение.

$ls -alh

total 24K
drwxrwxr-x  2 arien arien 4.0K Dec 28 20:56 .
drwxrwxr-x 18 arien arien 4.0K Dec 27 22:20 ..
-rwxrwxr-x  1 arien arien 8.5K Dec 28 20:56 fopen
-rw-rw-r--  1 arien arien  290 Dec 28 20:56 fopen.c
-rwx------  1 arien arien    0 Dec 28 20:55 hello.txt

Небольшой совет: если вы используете Ubuntu или Debian, вы можете увидеть описание функций с помощью man [function_name] man-страницфункции open () .

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...