回答:
- カーネルスタックとユーザースタックの違いは何ですか?
要するに、何もない-メモリ内の別の場所(したがって、スタックポインタレジスタの別の値)を使用することを除いて、通常は別のメモリアクセス保護。つまり、ユーザーモードで実行する場合、カーネルメモリ(その一部はカーネルスタックです)は、マップされていてもアクセスできません。逆に、カーネルコードから明示的に要求されない限り(Linuxでは、などの関数を介してcopy_from_user()
)、ユーザーメモリ(ユーザースタックを含む)には通常、直接アクセスできません。
- [別の]カーネルスタックが使用されるのはなぜですか?
特権とセキュリティの分離。1つは、ユーザー空間プログラムはスタック(ポインタ)を好きなように作成できることであり、通常、有効なものを用意するだけのアーキテクチャ要件はありません。したがって、カーネルは、ユーザースペースのスタックポインタが有効でも使用可能でも信頼できないため、独自の制御下で1つのセットを必要とします。異なるCPUアーキテクチャは、これを異なる方法で実装します。x86 CPUは、特権モードの切り替えが発生すると自動的にスタックポインターを切り替え、さまざまな特権レベルに使用される値は、特権コード(つまり、カーネルのみ)によって構成可能です。
- ISRでローカル変数が宣言されている場合、それはどこに格納されますか?
カーネルスタック上。カーネル(Linuxカーネル)は、 ISRを直接x86アーキテクチャの割り込みゲートにフックしませんが、代わりに、割り込みディスパッチを、登録済みハンドラーを呼び出す前に割り込み前のレジスタ状態を保存する共通のカーネル割り込みエントリ/出口メカニズムに委任します。 。割り込みをディスパッチするときのCPU自体が特権やスタックスイッチを実行する可能性があり、これはカーネルによって使用/設定されるため、共通の割り込みエントリコードはすでに存在するカーネルスタックに依存できます。
つまり、カーネルコードの実行中に発生する割り込みは、その時点でカーネルスタックをそのまま(引き続き)使用します。これは、割り込みハンドラーが深くネストされた呼び出しパスを持っている場合、スタックオーバーフローを引き起こす可能性があります(深いカーネル呼び出しパスが中断され、ハンドラーが別の深いパスを引き起こす場合.Linuxでは、iptablesがアクティブなネットワークコードによってファイルシステム/ソフトウェアRAIDコードが中断されますチューニングされていない古いカーネルでそのようなトリガーとなることが知られています...ソリューションは、そのようなワークロードのカーネルスタックサイズを増やすことです)。
- 各プロセスには独自のカーネルスタックがありますか?
各プロセスだけでなく、各スレッドには独自のカーネルスタックがあります(実際、独自のユーザースタックもあります)。プロセスとスレッド(Linuxにとって)の唯一の違いは、複数のスレッドがアドレス空間を共有できる(プロセスを形成する)ことです。
- プロセスはこれらの両方のスタック間でどのように調整しますか?
いいえ、必要ありません。スケジューリング(どのように/異なるスレッドが実行されているか、その状態がどのように保存および復元されるか)は、オペレーティングシステムのタスクであり、プロセスはこれに関与する必要はありません。スレッドが作成されると(各プロセスには少なくとも1つのスレッドが必要です)、カーネルはそれらのカーネルスタックを作成しますが、ユーザー空間スタックは、スレッドの作成に使用されるメカニズム(呼び出し元のような関数makecontext()
またはpthread_create()
呼び出しを許可する関数)によって明示的に作成または提供されます。「子」スレッドのスタックに使用するメモリ領域を指定する)または(新しいプロセスを作成するときに、通常「コピーオンライト」/ COWと呼ばれるオンアクセスメモリクローンによって)継承されます。
それは言った、(状態、その中のスレッドのスタックポインタ)。UNIX信号は、:あり、このために複数の方法がありますがsetcontext()
、pthread_yield()
/ pthread_cancel()
、... -これは元の質問から少しdisgressingています。
私の答えは、他のSOの質問から収集したものです。
What's the difference between kernel stack and user stack?
カーネルプログラマーは、カーネルを誤ったユーザープログラムから制限する必要があることを知っています。カーネルとユーザー空間の両方で同じスタックを保持するとします。その後、ユーザーアプリケーションの単純なsegfaultがカーネルをクラッシュさせ、再起動が必要になるとします。
ISRスタックのようにCPUごとに1つの「カーネルスタック」と、プロセスごとに1つの「カーネルスタック」があります。各スレッドには、ユーザースレッドとカーネルスレッドの両方を含む独自のスタックがありますが、プロセスごとに1つの「ユーザースタック」があります。
http://linux.derkeiler.com/Mailing-Lists/Kernel/2004-10/3194.html
Why kernel stack is used?
したがって、カーネルモードでは、関数呼び出し、ユーザー空間と同様のローカル変数を処理するために、スタックのようなメカニズムが必要です。
http://www.kernel.org/doc/Documentation/x86/kernel-stacks
If a local variable is declared in an ISR, where it will be stored?
ISRスタック(IRQSTACKSIZE)に格納されます。ISRは、ハードウェアがサポートしている場合にのみ、別の割り込みスタックで実行されます。それ以外の場合、ISRスタックフレームは、中断されたスレッドのスタックにプッシュされます。
ユーザー空間は、割り込みが現在のプロセスのカーネルスタックで処理されるのか、別のISRスタックで処理されるのかを知りませんし、率直に言っても気にしません。割り込みはCPUごとに発生するため、ISRスタックはCPUごとでなければなりません。
Does each process has its own kernel stack ?
はい。各プロセスには、独自のカーネルスタックがあります。
Then how the process coordinates between both these stacks?
@FrankHの答えは私には素晴らしく見えます。
- カーネルスタックとユーザースタックの違いは何ですか
Robert LoveのLinux Kernel Developmentを参考にすると、主な違いはサイズです。
ユーザー空間は、巨大な構造や1000要素の配列など、スタック上の多くの変数を静的に割り当てることで回避できます。
ユーザー空間には動的に拡大できる大きなスタックがあるため、この動作は合法です。
カーネルスタックは大きくも動的でもありません。それは小さく、サイズは固定されています。
カーネルのスタックの正確なサイズは、アーキテクチャによって異なります。
x86では、スタックサイズはコンパイル時に構成可能で、4KBまたは8KBのいずれかです。
歴史的に、カーネルスタックは2ページです。つまり、32ビットアーキテクチャでは8KB、64ビットアーキテクチャでは16KBです。このサイズは固定で絶対です。
各プロセスは独自のスタックを受け取ります。
また、カーネルスタックには、スレッドに関する情報を保持するthread_info構造体へのポインターが含まれています。