Write() выполняет по-разному в двух ситуациях

Итак, я должен был решить это упражнение:

Это упражнение предназначено для демонстрации того, почему атомарность, гарантированная открытием файла с флагом O_APPEND, необходима. Напишите программу, которая принимает до трех аргументов командной строки:

$ atomic_append filename num-bytes [x] 

Этот файл должен открыть указанное имя файла (при необходимости создав его) и добавить num-bytes bytes в файл, используя write() для записи байта за раз. По умолчанию программа должна открыть файл с флагом O_APPEND, но если указан третий аргумент командной строки (x), то флаг O_APPEND должен быть опущен, и вместо этого программа должна выполнить lseek(fd, 0, SEEK_END) вызов перед каждым write(). Запускайте два экземпляра этой программы одновременно без аргумента x, чтобы записать 1 миллион байт в один и тот же файл:

$ atomic_append f1 1000000 & atomic_append f1 1000000 

Повторите те же шаги, записывая в другой файл, но на этот раз указав аргумент x:

$ atomic_append f2 1000000 x & atomic_append f2 1000000 x 

Перечислите размеры файлов f1 и f2 с помощью ls –l и объясните разницу.

Так вот что я написал:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <fcntl.h>

int main(int argc, char *argv[]) {
        int fd, flags, num_bytes;
        if (argc < 3 || strcmp(argv[1], "--help") == 0) {
                printf("Usage: %s filename num-bytes [x]\n", argv[0]);
                return 1;
        }
        num_bytes = atoi(argv[2]);
        if (argc == 4 && strcmp(argv[3], "x") == 0) {
                fd = open(argv[1], O_CREAT | O_WRONLY, 0666);
                if (fd == -1)
                        perror("open");
                while (num_bytes-- > 0) {
                        lseek(fd, 0, SEEK_END);
                        write(fd, "a", 1);
                }
                if (close(fd) == -1)
                        perror("close");
        }
        else {
                fd = open(argv[1], O_CREAT | O_APPEND | O_WRONLY, 0666);
                if (fd == -1)
                        perror("open");
                while(num_bytes-- > 0)
                        write(fd, "a", 1);
                if (close(fd) == -1)
                        perror("close");
        }
        return 0;
}

Теперь, после того как я запустил его, как требуется:

[email protected]:~/System/5$ ./a.out f1 1000000 & ./a.out f1 1000000
[1] 4335
[1]+  Done                    ./a.out f1 1000000
[email protected]:~/System/5$ ./a.out f2 1000000 x & ./a.out f2 1000000 x
[1] 4352
[1]+  Done                    ./a.out f2 1000000 x
[email protected]:~/System/5$ ls f1 f2
f1  f2
[email protected]:~/System/5$ ls -l f*
-rw-rw-r-- 1 abhinav abhinav 2000000 Dec 10 16:23 f1
-rw-rw-r-- 1 abhinav abhinav 1000593 Dec 10 16:24 f2

Определенно, есть разница в размерах файлов, которые я не могу понять, почему? Я искал и нашел здесь это объяснение:

Размеры были определенно разными:

-rw------- 1 posborne posborne 1272426 2012-01-15 21:31 test2.txt
-rw------- 1 posborne posborne 2000000 2012-01-15 21:29 test.txt

Где test2.txt запускался без O_APPEND. test2.txt является коротким количество раз (или байтов в результате времени), которые стремятся к конец файла не происходил одновременно с записью (довольно часто).

Но это, похоже, не имеет никакого смысла. Итак, почему разница в размерах?

+4
источник поделиться
1 ответ

Этот код запускается в файле, не открытом с помощью O_APPEND:

            while (num_bytes-- > 0) {
                    lseek(fd, 0, SEEK_END);
                    write(fd, "a", 1);

записывает в местоположение конца файла, как это было при вызове lseek(). Конец файла может меняться в промежутке между вызовами lseek() и write().

Этот код в файле, который был открыт с помощью O_APPEND:

            while(num_bytes-- > 0)
                    write(fd, "a", 1);

гарантируется стандартным поведением write() 'в файл, открытый с помощью O_APPEND, для записи в конец файла независимо от того, где этот конец.

То, что вся точка флага O_APPEND - lseek(), а затем write() не работает.

+1
источник

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