Как буферизовать и записать на диск вход с низкой задержкой с помощью C
Мне нужно написать код C (не C# или C++), чтобы получить данные из аппаратного анализатора (через сеть TCP/IP 100 Мб) и записать их на диск.
Почему я говорю "Низкая задержка", ну, аппаратный анализатор имеет внутренний буфер 9 КБ, это 2 мс хранения данных, после чего происходит переполнение буфера, и я теряю информационные пакеты.
Мое приложение может получить этот буфер без потери пакетов, но я заметил, что не смог записать данные на диск с такой скоростью.
Мой код выглядит так:
int main (int argc, char * argv [] )
{
pthread_t th_rx; /* Thread for receiving packets */
outputfile = fopen ("output.log", "wb");
link_open(); // open device link
pthread_create ( &th_rx, NULL, read_packets, 0 );
// running loop
fclose (outputfile);
pthread_exit(NULL);
link_close(); // close device link
return 0;
}
static thread_result read_packets (void *arg)
{
char rxbuf[40960];
while (receiving)
{
bytes_received = read_packet(); //read packet from device buffer
rxbuf = extract_data(bytes_received);
fwrite (rxbuf, 1, bytes_received, outputfile);
}
return thread_return;
}
Здесь мне нужны идеи, как это сделать.
- 1: не писать пакет после получения, создать циркуляр? буфер
- 2: Создание двухпоточного кольцевого буфера?
Любые идеи о том, как улучшить мой код и что я могу сделать, чтобы получить стабильные записи?
Примеры кода будут очень полезны, потому что я чувствую себя потерянным:(
Спасибо
3 ответа
Как вы сказали, HW анализатор имеет 9 kb
память только для 2 ms
, Тогда скорость, необходимая для записи на HDD 9*1024*500 = 4608000 b/s or 4.6 Mb/s
, Я считаю, что тестовый компьютер имеет скорость записи на HDD не менее 10 Мб / с. Таким образом, единственной проблемой здесь является запись на жесткий диск с такими большими порциями данных, которые могут дать достаточно времени для записи. Например, буфер может быть 1 сек или 4,6 Мб. Хранение такой части данных будет быстрее, чем сбор 1 с данных с устройства hw, и "поток записи" занимает не более 500 мс, чтобы выполнить свою работу. В реальной программе это время может отличаться, но в любом случае его должно быть достаточно для одноядерных систем.
Поэтому вы можете использовать два пинг-понга (один заполнен данными из hw, один хранится на жестком диске) с двумя потоками и без циклического буфера. Таким образом, вы можете использовать модель производителя / потребителя, которая хорошо описана и имеет много примеров.
Как вы уже догадались, первое, что вам нужно сделать, это не записывать на диск во время чтения с устройства.
создать кольцевой / кольцевой буфер (или просто список буферов) для хранения данных, считанных с устройства. Эта операция будет достаточно быстрой, чтобы память устройства не заполнялась.
- Однако, если чтение устройства неблокирует, вы можете захотеть спать, чтобы ваш цикл не перегружал процессор.
Один поток читает данные с устройства и помещает в буфер.
- В другом потоке продолжайте записывать буфер на диск.
Вы должны посмотреть на асинхронный ввод-вывод. Однако API-интерфейсы Async-I/O зависят от операционной системы, и вы не указали, какую ОС вы используете. Также ваше использование потоков не имеет смысла. Если вы хотите использовать потоки (вместо асинхронного ввода / вывода), то у вас будет один поток, выполняющий чтение пакета, а другой поток должен записывать. Помещение их обоих в один поток не даст вам никакой пользы.