簡體   English   中英

具有非原子讀寫的環形緩沖區

[英]Ring buffer with non-atomic reads and writes

上下文:實時嵌入式 ARM 微控制器。

如果可以原子地讀取或寫入緩沖區中的數據,則編寫無鎖、無等待的 SPSC 環形緩沖區是直截了當的。 但是,在許多情況下,緩沖區需要通過許多操作來讀取,或者通過許多操作來寫入。 如何實現 SPSC 無鎖環形緩沖區? (目標是環形緩沖區在溢出時覆蓋最舊的數據,而不是阻塞。)

假設正在讀取條目 N。 現在,寫指針追上了 N。如果 N 的讀還沒有開始,我們將簡單地覆蓋 N,並將讀指針前進到 N+1; N 成為最后一個條目(最近寫入),N+1 成為第一個條目(最近最少寫入)。 但是,現在,由於讀取正在進行,我們不想覆蓋 N。相反,我們需要使寫入指針 N + 1 和讀取指針 N + 2。

同樣,如果寫指針在 N,讀指針前進到 N-1。 如果對 N-1 的寫入完成,我們就可以讀取 N-1。 但是,如果寫入正在進行中怎么辦。

好像除了write ptr和read ptr之外,我們還需要知道write是否在進行,read是否在進行。 然而,使用這兩個額外的信息來構造保持環形緩沖區正確的不變量是非常困難的。

問題:

對於無鎖、無等待、溢出的 SPSC 環形緩沖區,在寫入完成之前不允許讀取項目,並且不允許覆蓋正在讀取的項目:

  1. 我們需要什么數據(除了讀指針和寫指針)?
  2. 哪些不變量適用於該數據?
  3. 我們如何使用它來構造緩沖區?

我不確定你到底在找什么,也不清楚你所說的非原子讀/寫是什么意思。 但是,我認為您可以使用序列鎖來實現這樣的數據結構。

讀者和作者都維護自己的當前項目指針。

每個項目都有一個關聯的序列號,該序列號最初為零。 編寫器首先增加它希望覆蓋的項目的序列號(設置一些奇數)。 然后它修改項目。 最后,作者將序列號再遞增一次(將其設置為下一個偶數值),然后前進到下一個項目。

另一方面,讀者首先檢查當前項目的序列號。 如果數字是奇數,則該項目正在修改中,因此讀者轉到第 1 號項目。 N+1。 否則,讀取器會復制該項目的數據,然后再次檢查序列號。 如果數字在此期間沒有變化,則讀者會閱讀剛才制作的副本。 如果確實發生了變化,讀者將丟棄該副本並轉到第 1 項。 N+1。

此外,如果序列號是偶數,讀者也可以檢查它是否不是太大,這可能發生在作者已經超越讀者並且已經完成寫入時。 為此,讀取器保留一個紀元號,最初為兩個(假設零表示一個空項),並在讀取每個完整緩沖區后將其增加兩個。 閱讀器只讀取序列號等於當前紀元的項目,並且每當它過早地看到下一個紀元的項目時,就會向前推進到下一個項目。

這與您的要求有點不同,因為您說您不想打擾讀者,而是希望作者在讀取過程中直接跳到 N+1,但我不明白這是什么意思這個要求的要點。 如果數據的副本已經完成,則可以認為單個項目的讀取是立即執行的,因此不能被中斷。 如果上面給出的方法不能滿足您的目標,請提供更多關於您對緩沖區的期望的詳細信息(除了它是非阻塞的,並且編寫器在溢出時覆蓋)。

對於單一生產者、單一消費者,處理這類事情的最簡單方法是向寫指針添加另一位。 將其向左移動,然后使用位 0 表示正在進行對此項目的寫入。

寫操作看起來像這樣:

  1. 以原子方式設置寫指針的低位,以指示對目標項的寫入正在進行中;
  2. 寫項目;
  3. 原子地增加寫指針(將清除低位)以指示寫完成和新的寫指針。

現在,您向讀者提供的保證應該僅限於您可以使用這些信息做什么。

你的這部分問題是有問題的:

現在,寫入指針趕上 N。[...] 由於讀取正在進行,我們不想覆蓋 N。相反,我們需要使寫入指針 N + 1 和讀取指針 N + 2 .

您可以管理這樣的事情,但是您在這里向讀者提供了哪些有用的保證? 根據相對時間,讀者將獲得新項目或舊項目。 是的,你已經保證它讀取的項目是有效的,但只有一種情況會滿足它的目的,所以當它得到錯誤的時候它仍然需要中止或重試。

所以我的建議只是讀者應該在讀取前后檢查寫指針。 通過指針的不同,可以判斷出writer在讀的過程中經歷的所有狀態,從而可以知道讀到的item是新的、舊的還是無效的。

如果你真的需要給讀者一些東西,那么你可以這樣做:

  1. 嘗試讀取讀取指針處的項目。
  2. 如果你得到一個無效的項目(部分覆蓋),那么閱讀下一個項目;
  3. 如果你得到一個無效的項目,然后 go 返回並再次閱讀初始項目,因為現在必須完成。
  4. 如果寫入器可能超快並在您嘗試讀取初始項時覆蓋了整個緩沖區,那么它可能再次無效,因此 go 回到 (2)。

但同樣,您在這種情況下提供的額外保證可能真的不值得額外的復雜性。 我最好調整您的閱讀器界面以指示無效閱讀。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM