2016-02-01 9 views
5

ビーグルボーンブラックのPREEMPT-RTパッチLinux OSにリアルタイムで優先順位を付けたロボットがあります。すべてのコードはCで書かれており、500Hzで動作しています。リアルタイム埋め込みLinuxでのデータロギング中にレイテンシが急上昇する

私はコードを実行するたびに数百ミリ秒の範囲でレイテンシに気付き、私が書いたデータロギング機能まで追跡しました。この待ち時間は、リアルタイム機能に依存するため、ロボットの制御が失敗する原因になります。

コードの関連部分は以下のとおりです。分かりやすくするためにたくさんのコードを削除しましたが、何かが必要な場合はこの投稿を編集します。

FILE *file; 

int main(int argc, char** argv) { 
    file = fopen(logname, "w"); 

    while (1) { 
     /* Control code stuff*/ 

     logData(); 

     time_msec = time_msec + controlLoopTime; 
    } 
} 

void logData() { 
    if (time_msec - logTimer_msec >= LOG_TIMER) { 
     logTimer_msec = time_msec; 

     if (!bLogCreated) { 
      fprintf(file, 
        "SensorData1 SensorData2 SensorDataN" 
        ); 
      bLogCreated = TRUE; 
     } 

     // log data to file 
     fprintf(file, 

       "%.2f %.2f\n", 

       sensorData1, sensorData2, sensorDataN 
     ); 
    } 
} 

複数の変数(恐らく20-50)のデータを良いレート、おそらく100-125Hzでログする必要があります。データは制御レート(2msごと)で記録する必要はありませんが、それを12msに減らしましたが、数分ごとにレイテンシスパイクが表示されます。

遅延は、fprintfコールの問題です。これはBeagleBone Blackの制限、私のコード、または単にデータロギングの性質ですか?

同様の質問がここに頼まれましたが、私の問題に対処していないようでした:fprintfを使用してFinding latency issues (stalls) in embedded Linux systems

+1

デフォルトでは、非ttyファイルハンドルはブロックされています。したがって、fprintfが4096バイト後にバッファがディスクにフラッシュされ、それによってレイテンシが発生する可能性があります。実際のログを別のスレッドにアウトソースすることはできませんか?ログメッセージをキューに入れ、ログスレッド内でデキューします。 – Ctx

+0

このコードは通常のプロセスの一部として実行されていますか?デバイスドライバをブロックするミューテックスやセマフォなどを制御していますか? – wallyk

+0

@jekso:ログ(p)スレッドを作成し、ダブルリンクリストのようなものをキューとして(先頭にエンキュー、最後にデキューします)、pthread_cond_wait/notifyを使って新しいエントリを通知します。 – Ctx

答えて

2

は、特にR/Tのロギングのために、膨大な時間シンクです。バイナリでロギングを行い、後でそれを印刷するユーティリティを書きます。

の代わりに:

fprintf(file,"%.2f %.2f %.2f",data1,data2,data3); 

の操作を行います。

fwrite(&data1,sizeof(double),1,file); 
fwrite(&data2,sizeof(double),1,file); 
fwrite(&data3,sizeof(double),1,file); 

さらに良い:

struct data { 
    double data1; 
    double data2; 
    double data3; 
    time_t event_time; 
    ... 
}; 

struct data data; 

fwrite(&data,sizeof(struct data),1,file); 

それはまだあまりにも遅いなら、リングキューに構造体を追加し、別のスレッドでエントリを書き出します。

ディスク書き込みは、[今]バイナリデータに追いつくリングキューを維持し、唯一のあなたは致命的なエラーを検出した場合に検討し、また


キュー検死をダンプすることができない場合書き込み時にmmapを使用してファイルにアクセスします。私の答え[ベンチマーク付き]を参照してください:read line by line in the most efficient way *platform specific*

+0

これは根本的な問題に対処するのではなく、おそらく4または10の要素だけ減少させますが、引き続き発生します。同じことをするより簡単なメカニズムは、大きなバッファ(16メガバイトなど)を割り当てた状態で[setvbuf() '](http://man7.org/linux/man-pages/man3/setbuf.3.html)を呼び出すことです。 – wallyk

+0

ありがとうございます。だから、 'fwrite'は本質的に速くなります、私のリアルタイムプロセスの途中でまだファイルに書き込んでいますが? 編集:私は上記のwallykのコメントを見ました。それが私の心配でした。私は書き込まれるデータの量を数回減らしただけで、レイテンシのスパイクの頻度を減らしましたが、それらを完全に排除しませんでした。 – jekso

+0

はい。 'fprintf'は、非常に遅い(例えば、100倍遅く)、特に浮動小数点では。私は、同様のロギング要件を持つ生産R/Tシステムを出荷したので、私はここから経験を語っています。ファイルの変更にバイナリ書き込みを行った後、まだ遅すぎる場合は、メモリリングバッファにデータを書き込み、エラーを検出すると最後のN個のエントリをダンプします。 –

関連する問題