Я хочу сделать «межпроцессное взаимодействие» с файлом посередине. производитель записывает сообщения в файл, а потребитель читает его.
Мой вопрос о производителе.
Предположим этот код:
#include <iostream>
#include <fstream>
using namespace std;
int main() {
// Create and open a "file in the middle" IPC
ofstream messagefile("filename.txt");
// Write to the file
messagefile << "Files can be tricky, hope you are reading all of this string at once\n";
// Close the file
MyFile.close();
}
Есть ли риск того, что сброс буфера (на любом уровне ОС или стандартной библиотеки) очистит эту строку более чем в одной части? Я хочу убедиться, что процессы-потребители считывают все сообщение за один раз. Что ты посоветуешь?
Я знаю, что потребитель может дождаться определенного символа, такого как «\n», но мой вопрос касается производителя.
Заранее большое спасибо
Это не может быть реализовано надежным способом. Составьте какой-нибудь протокол <70>Files can be tricky, hope you are reading all of this string at once\n.
Я думаю, что для межпроцессного взаимодействия вы должны использовать сокеты, а не файлы.
Небольшой момент: вам не нужно звонить MyFile.close();. Это сделает деструктор.
Это не указано в стандарте C++. В Linux с локальной файловой системой я ожидаю, что каждый отдельный системный вызов write() будет атомарным.
Да, риск есть, и надежного способа его предотвратить нет.
@SamVarshavchik Я не думаю, что write() гарантированно атомарна в Linux (или любой другой системе с разделением времени). Не в смысле "все это (ничего из этого) идет на диск". Если произойдет сбой системы, вы можете потерять последнюю часть данных. write() предполагается атомарным между процессами и потоками (если два актора пишут «одновременно» в одну и ту же цель, их данные не должны перекрываться) (но см. https://man7.org/linux/man- страницы/man2/write.2.html).
Вам нужно будет использовать какую-то сигнализацию, чтобы указать, что файл записывается и когда он завершен. Вы действительно не хотите, чтобы задачи записывали в файл одновременно, -- поведение undefined.
Я также предлагаю какую-то сигнализацию или событие, чтобы сообщить другому процессу, что в файле есть данные.
Если вас беспокоит возможная потеря информации из-за сбоя системы, я бы посоветовал вам использовать ostream::flush плюс какой-то зависящий от операционной системы вызов для действительного сброса буферов ввода-вывода на диск (например, sync() в системах Unix).
Если вас интересует только протокол IPC (то есть вы просто хотите избежать чтения неполных сообщений), использования терминатора должно быть достаточно. В некоторых ситуациях могут быть полезны две разные отдельные «метки» (начало и конец).
Я предполагаю, что у вас одновременно активен только один писатель.
Или, что касается возможной ситуации с потерей данных, просто старайтесь писать чаще и меньшими порциями. :)
Спасибо за ваш ответ. Я думаю, что, наконец, я должен сделать какой-то протокол. но пока, я надеюсь, я смогу найти надежный способ только со стороны производителя
Для этого небольшого текста все должно поместиться в один буфер. Но если у вас есть текст намного большего размера, у вас возникнут проблемы, возможно, с несколькими сбросами. Вы всегда можете использовать блокировку файлов для конкретной ОС, чтобы предотвратить открытие файла другими процессами, пока вы не разблокируете его доступ.