目次
序文
バッファの主な目的は、データ転送中の速度不一致の問題を解決することです。データの送信側と受信側では、速度や処理能力が異なることがよくあります。送信者はより速い速度でデータを生成することができますが、受信者はより遅い速度でデータを受信して処理することができます。データの消失を回避するには、データをバッファリングするための中間記憶領域が必要です。
次にQTを例に分かりやすいバッファについてお話しますが、もちろんC言語でも実装できますので、この考え方は参考になります。
1. バッファー方法 1
主なアイデアは、バッファ スペースを申請し、そのスペースのフラグ ビットを使用することで相互に支援することです。複数のバッファ スペースを含む、バッファリングが必要なデータ プールがあると想定します。最初は、すべてのバッファのフラグ ビットが false に設定され、アイドル状態を示します。簡単に言うと、データはフラグ ビットを通じて解放され、データが追加されてバッファリング効果が得られます。
2. 初期化
2.1 バッファの初期化
最初のステップはスペースを申請することで、サイズは SIZE_BOOL * SIZE_HD で、この部分がバッファースペースです。
また、フラグ ビット用のスペースを確保するために、bool 型を使用する、よりメモリを節約する方法を選択します。
#define SIZE_BOOL 500
#define SIZE_HD 4
VCI_CAN_OBJ *G_frameBuffers = new VCI_CAN_OBJ[ SIZE_BOOL * SIZE_HD ];
bool * G_frame_flag = new bool[SIZE_BOOL];
VCI_CAN_OBJ はカスタム構造体です。これは CAN です。開発中に、自分のメモリを置き換えるだけで済みます。構造体がない場合は、変数を使用することもできます。
typedef struct _VCI_CAN_OBJ{
UINT ID;
UINT TimeStamp;
BYTE TimeFlag;
BYTE SendType;
BYTE RemoteFlag;
BYTE ExternFlag;
BYTE DataLen;
BYTE Data[8];
BYTE Reserved[3]; ֡
}VCI_CAN_OBJ,*PVCI_CAN_OBJ;
2.2 ヘッダファイルの説明
以下にこのバッファのヘッダファイルを記載しますので簡単に説明します。
FreeFrame_hd_Buffers: バッファを解放する関数。
Frame_hd_Buffer: この関数は、指定された場所のデータ アドレスを返す役割を果たします。
GetEmptyFrame_hd_Buffers: この関数は、空き位置バッファーをチェックし、位置を返す役割を果たします。
G_idx: バッファは現在位置を使用します
G_mutexBuffer: ミューテックス ロック
上記の説明からわかるように、この方法は比較的単純で、収集に適しており、将来の使用にも便利です。
#ifndef FRAMEHDPOOL_H
#define FRAMEHDPOOL_H
#include <QObject>
#include <QMutex>
#include <QList>
#include "controlcan.h"
#define SIZE_BOOL 500
#define SIZE_HD 2
class framehdpool : public QObject
{
Q_OBJECT
public:
explicit framehdpool(QObject *parent = nullptr);
~framehdpool();
void FreeFrame_hd_Buffers(int idx);
PVCI_CAN_OBJ Frame_hd_Buffer(int idx);
PVCI_CAN_OBJ GetEmptyFrame_hd_Buffers(int *idx);
private:
int G_idx;
VCI_CAN_OBJ *G_frameBuffers;
bool *G_frame_flag;
QMutex G_mutexBuffer;
signals:
};
#endif // FRAMEHDPOOL_H
3. 機能説明
3.1 初期化関数
初期化関数は比較的単純で、スペースを適用してデフォルト値を初期化します。
framehdpool::framehdpool(QObject *parent)
: QObject{parent}
{
G_idx = 0;
G_frameBuffers = new VCI_CAN_OBJ[ SIZE_BOOL * SIZE_HD ];
G_frame_flag = new bool[SIZE_BOOL];
if(G_frame_flag != nullptr) {
for(int i=0; i<SIZE_BOOL; i++)
G_frame_flag[i] = false;
}
}
3.2 リリース機能
もちろんアプリケーションがあればリリースが必要ですが、ここではQTのデストラクタで大丈夫ですが、C言語の場合は手動でリリースする必要があります。
framehdpool::~framehdpool()
{
if(G_frameBuffers != nullptr) {
delete [] G_frameBuffers;
G_frameBuffers = nullptr;
}
if(G_frame_flag != nullptr) {
delete [] G_frame_flag;
G_frame_flag = nullptr;
}
}
3.3 空きバッファの取得(ポイント)
この関数は主に、空きバッファ位置を見つけて、空き位置のアドレスを返す役割を果たします。
説明: 変数を適用し、変数を渡し、ポインターを介して変数を変更して自由な位置を取得する必要があります。たとえば、以下に示すように、frm バッファの場所とバッファの特定の場所の 2 つのキー データを取得できるため、この 2 つのデータを渡すときに、これら 2 つのデータを渡すだけで済みます。処理機能です。
int index_num = -1;
PVCI_CAN_OBJ * frm = GetEmptyFrame_hd_Buffers(&index_num );
関数のプロトタイプは次のとおりです。 (誰でも理解できるはずです。メッセージが理解できない場合、または私にプライベート メッセージを送ってください。詳細は説明しません)
PVCI_CAN_OBJ framehdpool::GetEmptyFrame_hd_Buffers(int *idx)
{
PVCI_CAN_OBJ frm;
*idx = -1;
frm = nullptr;
if(G_frameBuffers == nullptr || G_frame_flag == nullptr)
return nullptr;
G_mutexBuffer.lock();
int i = 0;
while (i < SIZE_BOOL) {
if(!G_frame_flag[G_idx]) {
G_frame_flag[G_idx] = true;
*idx = G_idx;
frm = G_frameBuffers + G_idx * SIZE_HD;
break;
}
G_idx = (G_idx + 1) % SIZE_BOOL;
i ++;
}
G_mutexBuffer.unlock();
return frm;
}
3.4 バッファの解放
ここでの解放バッファは、スペースを直接解放するのではなく、このスペースの符号を解放し、このスペースが引き続き使用できることを示します。
関数プロトタイプ:
//释放空间的标志位
void framehdpool::FreeFrame_hd_Buffers(int idx)
{
if(G_frameBuffers == nullptr || G_frame_flag == nullptr)
return;
G_mutexBuffer.lock();
G_frame_flag[idx] = false;
G_mutexBuffer.unlock();
}
3.5 指定位置データの取得
指定されたデータの場所を直接返します。プロトタイプは比較的シンプルで、呼び出すのに便利です。
関数プロトタイプ:
PVCI_CAN_OBJ framehdpool::Frame_hd_Buffer(int idx)
{
return G_frameBuffers + ( idx * SIZE_HD );
}
4. まとめ
要約すると、この記事ではフラグ ビットに基づくバッファ管理の実装を紹介し、バッファ スペースとフラグ ビットの適用の連携を通じて、データ バッファリング効果を実現します。この方法により、データ伝送中にさまざまなコンポーネント間の速度差のバランスをとることができ、データのスムーズな伝送と処理が保証されます。バッファを適切に管理および利用することで、プログラムのパフォーマンスと効率を向上させることができます。