Может ли несколько процессов присоединяться к файлу с помощью fopen без каких-либо проблем concurrency?

У меня есть процесс открытия файла в режиме добавления. В этом случае это файл журнала. Пример кода:

int main(int argc, char **argv) {
    FILE *f;
    f = fopen("log.txt", "a");
    fprintf(f, "log entry line");
    fclose(f);
}

Два вопроса:

  • Если у меня есть несколько процессов, связанных с одним и тем же файлом, будет ли каждая строка журнала отображаться отчетливо или может быть чересстрочная развертка в качестве переключателя контекста процессов?
  • Будет ли этот блок записи, если многие процессы требуют доступа к файлу, что вызывает проблемы concurrency?

Я рассматриваю возможность сделать это в своем простом воплощении или использовать zeromq для накачки записей журнала по трубам в сборщик журналов.

Я рассматривал syslog, но я действительно не хочу, чтобы какие-либо зависимости платформы от программного обеспечения.

По умолчанию платформа Linux для этого BTT.

Ответ 1

У вас наверняка будут зависимости от платформы, поскольку Windows не может обрабатывать несколько процессов, добавляя к одному и тому же файлу.

Что касается проблем синхронизации, я думаю, что вывод строки/буфера/должен/сэкономить большую часть времени, то есть более 99,99% коротких строк журнала должны быть неповрежденными в соответствии с моим коротким испытанием на основе оболочки, но не каждый раз. Явная семантика, безусловно, предпочтительнее, и поскольку вы не сможете писать эту систему взлома - независимо друг от друга, я бы рекомендовал подход syslog.

Ответ 2

Я не знаю о fopen и fprintf, но вы можете open использовать файл O_APPEND. Затем каждый write будет идти в конце файла без заминки (не смешиваясь с другой записью).

Собственно, смотря в стандарте:

Дескриптор файла, связанный с открытым потоком, должен быть назначается и открывается, как если бы по вызову open() со следующим флаги:

a or ab          O_WRONLY|O_CREAT|O_APPEND

Поэтому я думаю, что это безопасно для fprintf из нескольких процессов, пока файл был открыт с помощью a.

Ответ 3

стандарт (для open/write, not fopen/fwrite) указывает, что

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

Для использования fprintf() вам необходимо отключить буферизацию в файле.

Ответ 4

Когда ваши процессы будут писать что-то вроде:

"Here process #1"
"Here process #2"

вы, вероятно, получите что-то вроде:

"Hehere process #2re process #1"

Вам нужно будет синхронизировать их.

Ответ 5

ИЗМЕНИТЬ, чтобы ответить на ваши вопросы явно:

  • Если у меня есть несколько процессов, связанных с одним и тем же файлом, будет ли каждая строка журнала отображаться отчетливо или может быть чересстрочная развертка в качестве переключателя контекста процессов?

Да, каждая строка журнала будет выглядеть неповрежденной, поскольку согласно msdn/vs2010:

" Эта функция [то есть fwrite()] блокирует вызывающий поток и поэтому является потокобезопасной. Для неблокирующей версии см. _fwrite_nolock."

То же самое подразумевается в справочной странице GNU:

"- Функция: size_t fwrite (const void * data, size_t size, size_t count, FILE * stream)

This function writes up to count objects of size size from the array data, to the stream stream. The return value is normally count, if the call succeeds. Any other value indicates some sort of error, such as running out of space. 

- Функция: size_t fwrite_unlocked (const void * data, size_t size, size_t count, FILE * stream)

The fwrite_unlocked function is equivalent to the fwrite function except that it does not implicitly lock the stream.

This function [i.e., fwrite_unlocked( )] is a GNU extension. "
  • Будет ли этот блок записи, если многие процессы требуют доступа к файлу, что вызывает проблемы concurrency?

Да, по смыслу вопроса 1.

Ответ 6

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