Как буферизовать и записать на диск вход с низкой задержкой с помощью 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 зависят от операционной системы, и вы не указали, какую ОС вы используете. Также ваше использование потоков не имеет смысла. Если вы хотите использовать потоки (вместо асинхронного ввода / вывода), то у вас будет один поток, выполняющий чтение пакета, а другой поток должен записывать. Помещение их обоих в один поток не даст вам никакой пользы.

Другие вопросы по тегам