Системные вызовы C open/read/write/close и O_CREAT|O_EXCL

Учитывая следующий код (предполагается записать «helloworld» в файл «helloworld», а затем прочитать текст):

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

#define FNAME "helloworld"

int main(){ 
    int filedes, nbytes;
    char buf[128];

    /* Creates a file */
    if((filedes=open(FNAME, O_CREAT | O_EXCL | O_WRONLY | O_APPEND, 
        S_IRUSR | S_IWUSR)) == -1){
            write(2, "Error1\n", 7);
    }

    /* Writes hello world to file */
    if(write(filedes, FNAME, 10) != 10)
        write(2, "Error2\n", 7);

    /* Close file */
    close(filedes);

    if((filedes = open(FNAME, O_RDONLY))==-1)
        write(2, "Error3\n", 7);

    /* Prints file contents on screen */    
    if((nbytes=read(filedes, buf, 128)) == -1)
        write(2, "Error4\n", 7);

    if(write(1, buf, nbytes) != nbytes)
        write(2, "Error5\n", 7);

    /* Close file after read */
    close(filedes); 

    return (0);
}

При первом запуске программы вывод такой:

helloworld

После этого каждый раз, когда я запускаю программу, вывод:

Error1
Error2
helloworld

Я не понимаю, почему текст не добавляется, так как я указал файл O_APPEND. Это потому, что я включил O_CREAT? Если файл уже создан, не следует ли игнорировать O_CREAT?


person Andrei Ciobanu    schedule 03.04.2010    source источник


Ответы (1)


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

Он используется для обеспечения того, чтобы файл был создан с заданными разрешениями, переданными в третьем параметре. Короче говоря, у вас есть следующие варианты:

  • O_CREAT: Создайте файл с заданными разрешениями, если файл еще не существует. Если файл существует, он открывается, а разрешения игнорируются.
  • O_CREAT | O_EXCL: Создайте файл с заданными разрешениями, если файл еще не существует. Если файл существует, он терпит неудачу. Это полезно для создания файлов блокировки и гарантии эксклюзивного доступа к файлу (при условии, что все программы, использующие этот файл, используют один и тот же протокол).
  • O_CREAT | O_TRUNC: Создайте файл с заданными разрешениями, если файл еще не существует. В противном случае усеките файл до нуля байтов. Это имеет больший эффект, чем мы ожидаем, когда думаем «создать новый пустой файл». Тем не менее, он сохраняет разрешения, уже имеющиеся в существующем файле.

Дополнительная информация на справочной странице:

O_EXCL

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

person Juliano    schedule 03.04.2010
comment
Спасибо, после удаления O_EXCL код работает. Не могли бы вы объяснить мне использование O_EXCL. - person Andrei Ciobanu; 04.04.2010