stringtranslate.com

Круговой буфер

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

В информатике кольцевой буфер , кольцевая очередь , циклический буфер или кольцевой буфер — это структура данных , которая использует один буфер фиксированного размера , как если бы он был соединен сквозным образом. Эта структура легко подходит для буферизации потоков данных . [1] Были ранние реализации кольцевого буфера в оборудовании. [2] [3]

Обзор

Кольцевой буфер клавиатуры на 24 байта. Когда указатель записи почти достигает указателя чтения — поскольку микропроцессор не отвечает — буфер прекращает запись нажатий клавиш. На некоторых компьютерах раздается звуковой сигнал.

Круговой буфер изначально пуст и имеет заданную длину. На схеме ниже представлен буфер из 7 элементов:

Предположим, что 1 записано в центре кольцевого буфера (точное начальное местоположение не имеет значения в кольцевом буфере):

Затем предположим, что в кольцевой буфер добавляются еще два элемента — 2 и 3 — которые помещаются после 1:

Если два элемента удаляются, два самых старых значения внутри кольцевого буфера будут удалены. Кольцевые буферы используют логику FIFO ( первым пришел, первым вышел ). В этом примере 1 и 2 были первыми, кто попал в кольцевой буфер, они первыми будут удалены, оставив 3 внутри буфера.

Если буфер содержит 7 элементов, то он полностью заполнен:

Свойство кольцевого буфера заключается в том, что когда он заполнен и выполняется последующая запись, он начинает перезаписывать самые старые данные. В текущем примере добавляются еще два элемента — A и B — и они перезаписывают 3 и 4:

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

Наконец, если теперь удалить два элемента, то будут удалены не 3 и 4 (или, скорее, теперь A и B), а 5 и 6, поскольку 5 и 6 теперь являются самыми старыми элементами, что дает буфер с:

Использует

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

Кольцевая буферизация является хорошей стратегией реализации для очереди с фиксированным максимальным размером. Если максимальный размер принимается для очереди, то кольцевой буфер является совершенно идеальной реализацией; все операции очереди происходят за постоянное время. Однако расширение кольцевого буфера требует сдвига памяти, что сравнительно затратно. Для произвольного расширения очередей может быть предпочтительнее подход со связанным списком .

В некоторых ситуациях может использоваться перезапись кольцевого буфера, например, в мультимедиа. Если буфер используется как ограниченный буфер в проблеме производитель-потребитель , то, вероятно, желательно, чтобы производитель (например, аудиогенератор) перезаписывал старые данные, если потребитель (например, звуковая карта ) не может в данный момент успеть. Кроме того, семейство алгоритмов сжатия данных без потерь LZ77 работает на основе предположения, что строки, которые были недавно замечены в потоке данных, с большей вероятностью вскоре появятся в потоке. Реализации хранят самые последние данные в кольцевом буфере.

Круговая буферная механика

Реализация кольцевого буфера в аппаратном обеспечении, патент США 3979733, рис.4

Кольцевой буфер можно реализовать с помощью указателя и трех целых чисел: [4]

На этом изображении показан частично заполненный буфер с длиной = 7:

На этом изображении показан полный буфер с четырьмя перезаписанными элементами (номера от 1 до 4):

В начале индексы end и start устанавливаются в 0. Операция записи в циклический буфер записывает элемент в конечную позицию индекса, а конечный индекс увеличивается до следующей позиции буфера. Операция чтения в циклическом буфере считывает элемент из начальной позиции индекса, а начальный индекс увеличивается до следующей позиции буфера.

Начальных и конечных индексов самих по себе недостаточно для различения состояния буфера: заполнен или пуст, при этом используются все слоты буфера, [5] но это возможно, если максимальный используемый размер буфера равен Length - 1. [6] В этом случае буфер пуст, если начальный и конечный индексы равны и заполнены, когда используемый размер равен Length - 1. Другое решение — иметь другой целочисленный счетчик, который увеличивается при операции записи и уменьшается при операции чтения. Тогда проверка на пустоту означает проверку счетчика на равенство 0, а проверка на заполненность означает проверку счетчика на равенство Length. [7]

Следующий исходный код представляет собой реализацию на языке C вместе с минимальным тестом. Функция put() помещает элемент в буфер, функция get() извлекает элемент из буфера. Обе функции заботятся о емкости буфера:

#include <stdio.h> enum { N = 10 }; // размер кольцевого буфера      int buffer [ N ]; // примечание: в данный момент времени может быть сохранено только (N - 1) элементов int writeIndx = 0 ; int readIndx = 0 ;         int put ( int item ) { if (( writeIndx + 1 ) % N == readIndx ) { // буфер заполнен, избегайте переполнения return 0 ; } buffer [ writeIndx ] = item ; writeIndx = ( writeIndx + 1 ) % N ; return 1 ; }                             int get ( int * value ) { if ( readIndx == writeIndx ) { // буфер пуст return 0 ; }               * значение = буфер [ readIndx ]; readIndx = ( readIndx + 1 ) % N ; возврат 1 ; }           int main () { // тест кольцевого буфера int value = 1001 ; while ( put ( value ++ )); while ( get ( & value )) printf ( "read %d \n " , value ); return 0 ; }                    

Оптимизация

Реализацию кольцевого буфера можно оптимизировать, сопоставив базовый буфер с двумя смежными областями виртуальной памяти . [8] [ discusseddiscussion ] (Естественно, длина базового буфера должна тогда равняться некоторому кратному размеру страницы системы .) Чтение из и запись в кольцевой буфер могут затем выполняться с большей эффективностью посредством прямого доступа к памяти; те доступы, которые выходят за пределы конца первой области виртуальной памяти, будут автоматически переноситься в начало базового буфера. Когда смещение чтения продвигается во вторую область виртуальной памяти, оба смещения — чтения и записи — уменьшаются на длину базового буфера.

Кольцевой буфер с элементами фиксированной длины и непрерывными блоками

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

Некоторые реализации кольцевого буфера используют элементы фиксированной длины, размер которых превышает 8 бит — 16-битные целые числа для аудиобуферов, 53-байтовые ячейки ATM для телекоммуникационных буферов и т. д. Каждый элемент является непрерывным и имеет правильное выравнивание данных , поэтому программное обеспечение, считывающее и записывающее эти значения, может работать быстрее, чем программное обеспечение, обрабатывающее несмежные и невыровненные значения.

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

Буфер bip (двусторонний буфер) очень похож на кольцевой буфер, за исключением того, что он всегда возвращает смежные блоки, которые могут быть переменной длины. Это обеспечивает почти все преимущества эффективности кольцевого буфера, сохраняя при этом возможность использования буфера в API, которые принимают только смежные блоки. [9]

Сжатые кольцевые буферы фиксированного размера используют альтернативную стратегию индексации, основанную на элементарной теории чисел, для поддержания сжатого представления фиксированного размера всей последовательности данных. [10]

Ссылки

  1. ^ Arpaci-Dusseau, Remzi H.; Arpaci-Dusseau, Andrea C. (2014), Операционные системы: три простых части [Глава: Условные переменные, рисунок 30.13] (PDF) , Книги Arpaci-Dusseau
  2. ^ Hartl, Johann (17 октября 2011 г.). "Impulswiederholer - Telephone Exchange (видео)". Youtube . Получено 15 декабря 2021 г. .
  3. ^ Фрейзер, Александр Гибсон. "Патент США 3979733 Пакетный коммутатор цифровой системы передачи данных". Патент США . Получено 15 декабря 2021 г.
  4. ^ Лю, З.; У, Ф.; Дас, СК (2021). Беспроводные алгоритмы, системы и приложения: 16-я международная конференция, WASA 2021, Нанкин, Китай, 25–27 июня 2021 г., Труды, часть II. Конспект лекций по информатике. Springer International Publishing. стр. 117. ISBN 978-3-030-86130-8. Получено 2023-09-04 .
  5. ^ Чандрасекаран, Сиддхарт (2014-05-16). «Реализация кольцевого буфера в Embedded C». Embed Journal . Команда EmbedJournal. Архивировано из оригинала 11 февраля 2017 г. Получено 14 августа 2017 г.
  6. ^ Круговые буферы kernel.org
  7. ^ Морин, Пэт . "ArrayQueue: очередь на основе массива". Открытые структуры данных (в псевдокоде) . Архивировано из оригинала 31 августа 2015 г. Получено 7 ноября 2015 г.
  8. ^ Майк Эш (2012-02-17). "mikeash.com: Пятничные вопросы и ответы 2012-02-17: Кольцевые буферы и зеркальная память: Часть II". mikeash.com . Архивировано из оригинала 2019-01-11 . Получено 2019-01-10 .
  9. ^ Саймон Кук (2003), «Бип-буфер — круговой буфер с изюминкой»
  10. ^ Гюнтер, Джон С. (март 2014 г.). «Алгоритм 938: Сжатие кольцевых буферов». ACM Transactions on Mathematical Software . 40 (2): 1–12. doi :10.1145/2559995. S2CID  14682572.

Внешние ссылки