vxworks のような RTOses では、タスクを作成するたびにスタックサイズが指定されます。タスクのスタックがオーバーフローしているかどうかをチェックするルーチンを C で記述できますか?
7 に答える
参考までに、checkStack() を使用して VxWorks のシェルからこのようなことを行うことができます。
スタックがどれだけ大きいかを知っていて、注意していれば、そうです (ただし、移植性はありません)。スタックのベース アドレスを取得する方法が他にない場合は、スレッドのメイン関数でスタック変数のアドレスを記録する必要があります。これにより、スタックの最上部の近似値が得られます。次に、チェック関数で、ローカル変数のアドレスを取得します。これにより、スタックの一番下が得られます。トップとボトムの違いがスタック サイズに関するものである場合は、心配する必要があります。差がスタック サイズよりも大きい場合は、心配しても手遅れです。つまり、損傷が発生しています (ただし、クリーンアップの方法を考える必要があります)。
VxWorks については知りませんが、私の記憶では、Green Hill の Velosity/uVelosity カーネルがこれを行うコードを提供しています。そうでなかったとしても、ユーザーが変更できるソースを提供し、インフラストラクチャが存在するため、追加するのは非常に簡単です。
編集: 開示のために、私は彼らと一緒に夏のインターンシップを行い、uVelosity を新しいアーキテクチャに移植しました。これが、私がスレッドスタックの処理に親しんだ方法です。
特定のアプリケーションがそのスレッドを静的に割り当てる場合、それらのスタックを静的に定義された領域に配置し、リンカー マップを使用してそれらの領域の最後にシンボルを配置することができます。次に、現在のスタックポインターを取得し(他の回答で説明されているように)、「スタックセグメントの終わり」ポインターをそのアドレスと比較するだけです。これは、スタックの最後として提供されたアドレスを格納する場所が各スレッドにある場合、動的割り当てにも機能します。
C はそれを行う方法を提供しませんが、基礎となるシステムについていくつかの仮定を立てることでそれを行うことができます。
Windows では、コンパイラで特に指定しない限り、スタック サイズのデフォルトは 1MB であり、常にラウンド メモリ アドレスに合わせられます。この情報に基づいて、次のような関数を使用して残りのスタックを見積もることができます。
unsigned long remaining_stack_size() {
char dummy;
return 0x000fffff & (unsigned long)&dummy;
// 0x000fffff is 1MB -1 (1048576 -1)
}
実際には現在のスタックアドレスを返すことに注意してください。これは、スタックポインタがいっぱいになると減少するため、残りのサイズと同じです。
コンセプトの証明:
#include <stdio.h>
#include <windows.h>
unsigned long remaining_stack_size() {
char dummy;
return 0x001fffff & (unsigned long)&dummy + 1; // okay, some minor adjusts
}
void recurse_to_death(unsigned long used, char *p) {
char buf[32*1024];
used += 32*1024;
printf("Used: 0x%08x Remaining: 0x%08x\n", used, remaining_stack_size());
recurse_to_death(used, buf);
}
DWORD WINAPI my_thread(void *p) {
printf("Total stack size of this Thread: 0x%08x bytes\n", remaining_stack_size() + 72);
recurse_to_death(0, NULL);
return 0;
}
int main(int argc, char *argv) {
DWORD tid;
// CreateThread's stack size actually defaults to 1MB+64KB and does not honor lower values
CreateThread(NULL, NULL, my_thread, NULL, NULL, NULL);
Sleep(30000);
return 0;
}
remaining_stack_size()
残りのサイズが に収束するのと同じように、スタック オーバーフローを予測します0
。