Несколько регистраторов, записывающих в один файл C

#c #logging

#c #ведение журнала

Вопрос:

Я пытаюсь реализовать сценарий ведения журнала, в котором для разных компонентов в проекте есть несколько регистраторов. Все эти регистраторы пытаются выполнить запись в файл. Существует ли какая-либо библиотека для этого или какой-либо способ синхронизации активности в C (как в Java).

Также используется один дескриптор.

Комментарии:

1. параллельная очередь для этого файла решила бы часть синхронизации.

2. Вы имеете в виду, что у каждого регистратора есть свой собственный дескриптор файла; или все они используют один дескриптор? И это многопоточно?

Ответ №1:

#include <mutex> в C 11 это сделает. Все, что вам нужно будет сделать, это передать номер файла каждой части программе потоку

Однако имейте в виду условия гонки.

Ответ №2:

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

В UNIX вы можете использовать мьютекс p_threads, а в Win32 — критические разделы.

 CRITICAL_SECTION my_mutex;

void initialise()
{
    InitializeCriticalSection(amp;my_mutex);
}

void log(const char *some text)
{
    EnterCriticalSection(amp;my_mutex);

    // do some logging

    LeaveCriticalSection(amp;my_mutex);
}
  

В UNIX все то же самое, за исключением использования:

 pthread_mutex_t my_mutex;
pthread_mutex_init(amp;my_mutex, NULL);   /// instead of InitializeCriticalSection()
pthread_mutex_lock(amp;my_mutex);         /// instead of EnterCriticalSection()
pthread_mutex_unlock(amp;my_mutex);       /// instead of LeaveCriticalSection()
  

Ответ №3:

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

Ответ №4:

Мьютекс — это переносимый и гарантированный подход.

Хотя это и не гарантировано, в обычных реализациях выходные данные любой отдельной ofstream << x операции никогда не смешиваются с операциями других потоков в том же потоке ( fstream т. Е. Предположительно Используется мьютекс или тщательно сконструированная внутренняя очередь без блокировок), поэтому, если вы избегаете этого…

 my_ofstream << x << y << 'n';  // troublesome: 3 fstream operations
  

… в пользу этого…

 std::ostringstream oss;
oss << x << y << 'n';
my_ofstream << oss.rdbuf();   // usually ok: 1 fstream operation
  

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