web-dev-qa-db-ja.com

カーネルスタックとユーザースペーススタック

カーネルスタックとユーザースタックの違いは何ですか?カーネルスタックが使用される理由ローカル変数がISRで宣言されている場合、どこに保存されますか?各プロセスには独自のカーネルスタックがありますか?次に、プロセスはこれらの両方のスタック間でどのように調整しますか?

91
jkv
  1. カーネルスタックとユーザースタックの違いは何ですか?

要するに、メモリ内の異なる場所(したがってスタックポインタレジスタの異なる値)を使用することと、通常は異なるメモリアクセス保護を使用することを除いて、何もありません。つまりユーザーモードで実行する場合、カーネルメモリ(一部はカーネルスタック)は、マップされていてもアクセスできません。逆に、カーネルコードによって明示的に要求されない限り(Linuxではcopy_from_user()などの関数を介して)、ユーザーメモリ(ユーザースタックを含む)は通常直接アクセスできません。

  1. [別の]カーネルスタックが使用される理由は?

特権とセキュリティの分離。 1つは、ユーザー空間プログラムがスタック(ポインター)を必要なものにできることです。通常、有効なものさえ持つアーキテクチャ要件はありません。そのため、カーネルはtrustが有効でも使用可能でもないユーザースペーススタックポインターを使用できないため、独自の制御下で1つのセットが必要になります。さまざまなCPUアーキテクチャがこれをさまざまな方法で実装しています。特権モードの切り替えが発生すると、x86 CPUは自動的にスタックポインターを切り替え、さまざまな特権レベルに使用される値は、特権コード(つまり、カーネルのみ)で構成可能です。

  1. ISRでローカル変数が宣言されている場合、どこに保存されますか?

カーネルスタック上。カーネル(Linuxカーネル、つまり)はnot x86アーキテクチャのISRを直接フック割り込みゲートしますが、代わりに割り込みディスパッチを一般的なカーネル割り込みエントリ/出口メカニズムに委任します登録済みハンドラーを呼び出す前に、割り込み前のレジスター状態を保存します。割り込みをディスパッチするときのCPU自体が特権やスタックスイッチを実行する可能性があり、これはカーネルによって使用/設定され、共通の割り込みエントリコードが既に存在するカーネルスタックに依存できるようにします。
つまり、カーネルコードの実行中に発生する割り込みは、その時点でカーネルスタックを使用する(続行する)だけです。これは、割り込みハンドラーが深くネストされた呼び出しパスを持っている場合、スタックオーバーフローを引き起こす可能性があります(深いカーネル呼び出しパスが中断され、ハンドラーが別の深いパスを引き起こす場合、Linuxでは、iptablesがアクティブなネットワークコードによってファイルシステム/ソフトウェアRAIDコードが中断されますチューニングされていない古いカーネルでこのようなトリガーを引き起こすことが知られています...解決策は、そのようなワークロードのカーネルスタックサイズを増やすことです)。

  1. 各プロセスには独自のカーネルスタックがありますか?

各プロセスだけでなく、各threadには独自のカーネルスタックがあります(実際、独自のユーザースタックもあります)。プロセスとスレッド(Linuxにとって)の唯一の違いは、複数のスレッドがアドレススペースを共有できる(プロセスを形成する)という事実であることに注意してください。

  1. プロセスはこれらの両方のスタック間でどのように調整しますか?

まったくありません-する必要はありません。スケジューリング(異なるスレッドの実行方法/実行時、状態の保存および復元方法)は、オペレーティングシステムのタスクであり、プロセスはこれに気を使う必要はありません。スレッドが作成されると(各プロセスには少なくとも1つのスレッドが必要です)、カーネルはそれらのカーネルスタックを作成しますが、ユーザースペーススタックはスレッドの作成に使用されるメカニズムによって明示的に作成/提供されます(makecontext()またはpthread_create()呼び出し元は、「子」スレッドのスタックに使用するメモリ領域を指定するか、継承時に(通常、「コピーオンライト」/ COWと呼ばれるオンアクセスメモリクローニングにより)新しいプロセス)。
それは、プロセスcanがそのスレッドのスケジューリングに影響を与える、および/またはcontext(状態、その中のスレッドのスタックポインター)に影響を与えます。これには複数の方法があります:UNIXシグナル、setcontext()pthread_yield()/pthread_cancel()、...-しかし、これは元の質問から少し逸脱しています。

165
FrankH.

私の回答は、他のSO質問を含む質問から収集されます。

What's the difference between kernel stack and user stack?

カーネルプログラマーとして、カーネルは誤ったユーザープログラムから制限されるべきであることを知っています。カーネルとユーザースペースの両方で同じスタックを保持し、ユーザーアプリケーションの単純なセグメンテーションフォールトがカーネルをクラッシュさせ、再起動が必要だと仮定します。

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の答えは私にとって素晴らしいと思います。

15
Jeyaram
  1. カーネルスタックとユーザースタックの違いは何ですか

Robert LoveのLinux Kernel Developmentを参考にすると、主な違いはサイズです。

ユーザー空間は、巨大な構造や数千要素の配列など、スタック上の多くの変数を静的に割り当てることで回避できます。
ユーザー空間には動的に成長できる大きなスタックがあるため、この動作は正当です。
カーネルスタックは大きくも動的でもありません。それは小さく、サイズが固定されています。
カーネルのスタックの正確なサイズは、アーキテクチャによって異なります。
x86では、スタックサイズはコンパイル時に構成可能で、4KBまたは8KBのいずれかです。
歴史的に、カーネルスタックは2ページであり、これは一般に、32ビットアーキテクチャでは8 KB、64ビットアーキテクチャでは16 KBであることを意味します。このサイズは固定で絶対です。
各プロセスは独自のスタックを受け取ります。

また、カーネルスタックには、スレッドに関する情報を保持するthread_info構造体へのポインターが含まれています。

3
arenard