【轉】環形緩衝區

來源:互聯網
上載者:User

標籤:

原文地址:http://blog.csdn.net/linlinlinxi007/article/details/5086806

在通訊程式中,經常使用環形緩衝區作為資料結構來存放通訊中發送和接收的資料。環形緩衝區是一個先進先出的迴圈緩衝區,可以向通訊程式提供對緩衝區的互斥訪問。 

1、環形緩衝區的實現原理 
環形緩衝區通常有一個讀指標和一個寫指標。讀指標指向環形緩衝區中可讀的資料,寫指標指向環形緩衝區中可寫的緩衝區。通過移動讀指標和寫指標就可以實現緩衝區的資料讀取和寫人。在通常情況下,環形緩衝區的讀使用者僅僅會影響讀指標,而寫使用者僅僅會影響寫指標。如果僅僅有一個讀使用者和一個寫使用者,那麼不需要添加互斥保護機制就可以保證資料的正確性。如果有多個讀寫使用者訪問環形緩衝區,那麼必須添加互斥保護機制來確保多個使用者互斥訪問環形緩衝區。 
圖1、圖2和圖3是一個環形緩衝區的運行。圖1是環形緩衝區的初始狀態,可以看到讀指標和寫指標都指向第一個緩衝區處;圖2是向環形緩衝區中添加了一個資料後的情況,可以看到寫指標已經移動到資料區塊2的位置,而讀指標沒有移動;圖3是環形緩衝區進行了讀取和添加後的狀態,可以看到環形緩衝區中已經添加了兩個資料,已經讀取了一個資料。 

伺服器公用組件實現----環形緩衝區 


  訊息佇列鎖調用太頻繁的問題算是解決了,另一個讓人有些苦惱的大概是這太多的記憶體配置和釋放操作了。頻繁的記憶體配置不但增加了系統開銷,更使得記憶體片段不斷增多,非常不利於我們的伺服器長期穩定運行。也許我們可以使用記憶體池,比如SGI STL中附帶的小記憶體 Clerk。但是對於這種按照嚴格的先進先出順序處理的,塊大小並不算小的,而且塊大小也並不統一的記憶體配置情況來說,更多使用的是一種叫做環形緩衝區的方案,mangos的網路代碼中也有這麼一個東西,其原理也是比較簡單的。 
  就好比兩個人圍著一張圓形的桌子在追逐,跑的人被網路IO線程所控制,當寫入資料時,這個人就往前跑;追的人就是邏輯線程,會一直往前追直到追上跑的人。如果追上了怎麼辦?那就是沒有資料可讀了,先等會兒唄,等跑的人向前跑幾步了再追,總不能讓遊戲沒得玩了吧。那要是追的人跑的太慢,跑的人轉了一圈過來反追上追的人了呢?那您也先歇會兒吧。要是一直這麼反著追,估計您就只能換一個跑的更快的追逐者了,要不這遊戲還真沒法玩下去。 
  前面我們特彆強調了,按照嚴格的先進先出順序進行處理,這是環形緩衝區的使用必須遵守的一項要求。也就是,大家都得遵守規定,追的人不能從桌子上跨過去,跑的人當然也不允許反過來跑。至於為什麼,不需要多做解釋了吧。 
  環形緩衝區是一項很好的技術,不用頻繁的分配記憶體,而且在大多數情況下,記憶體的反覆使用也使得我們能用更少的記憶體塊做更多的事。 
  在網路IO線程中,我們會為每一個串連都準備一個環形緩衝區,用於臨時存放接收到的資料,以應付半包及粘包(即發送方發送的若干包資料到接收方接收時粘成一包)的情況。在解包及解密完成後,我們會將這個資料包複製到邏輯線程訊息佇列中,如果我們只使用一個隊列,那這裡也將會是個環形緩衝區,IO線程往裡寫,邏輯線程在後面讀,互相追逐。可要是我們使用了前面介紹的最佳化方案後,可能這裡便不再需要環形緩衝區了,至少我們並不再需要他們是環形的了。因為我們對同一個隊列不再會出現同時讀和寫的情況,每個隊列在寫滿後交給邏輯線程去讀,邏輯線程讀完後清空隊列再交給IO線程去寫,一段固定大小的緩衝區即可。沒關係,這麼好的技術,在別的地方一定也會用到的   

 

 

2、執行個體:環形緩衝區的實現

環形緩衝區是資料通訊程式中使用最為廣泛的資料結構之一,下面的代碼,實現了一個環形緩衝區:

 1 /*ringbuf .c*/ 2 #include<stdio. h> 3 #include<ctype. h> 4  5 #define NMAX 8 6  7 int iput = 0; /* 環形緩衝區的當前放入位置 */ 8 int iget = 0; /* 緩衝區的當前取出位置 */ 9 int n = 0; /* 環形緩衝區中的元素總數量 */10 double buffer[NMAX];11 12 /* 環形緩衝區的地址編號計算函數,如果到達喚醒緩衝區的尾部,將繞回到頭部。環形緩衝區的有效地址編號為:0到(NMAX-1)*/13 int addring (int i)14 {15      return (i+1) == NMAX ? 0 : i+1;16 }17 18 /* 從環形緩衝區中取一個元素 */19 double get(void)20 {21         int pos;22         if (n>0)23         {24              Pos = iget;25              iget = addring(iget);26              n--;27              return buffer[pos];28         }29         else 30         {31             printf(“Buffer is empty/n”);32             return 0.0;33         }       34  }35 36 /* 向環形緩衝區中放入一個元素*/37 void put(double z)38 {39         if (n<NMAX)40         {41              buffer[iput]=z;42              iput = addring(iput);43              n++;44         }45         else46             printf(“Buffer is full/n”);47 }48 49  50 51 int main{void)52 {53         chat opera[5];54         double z;55         do 56         {57             printf(“Please input p|g|e?”);58             scanf(“%s”, &opera);59             switch(tolower(opera[0]))60             {61                    case ‘p’: /* put */62                        printf(“Please input a float number?”);63                        scanf(“%lf”, &z);64                        put(z);65                        break;66                     case ‘g’: /* get */67                         z = get();68                         printf(“%8.2f from Buffer/n”, z);69                         break;70                     case ‘e’:71                         printf(“End/n”);72                         break;73                     default:74                         printf(“%s - Operation command error! /n”, opera);75             }/* end switch */76         }while(opera[0] != ’e’);77         return 0;78 }

 

【轉】環形緩衝區

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.