Linux(カーネル解析):30 ---(スピンロック(スピンロック)、読み込み - 書き込みスピンロック(スピンwrlock))のカーネル同期

スピンロックの概要

  • 各クリティカル領域がうまく変数を増やすような単純なことができますが、現実は常に残酷である場合。現実の世界では、重要な地域であっても、複数の機能をまたがることができます。たとえば、私たちはしばしばこのような状況が発生した:フォーマット変換や解像度、および他のデータ構造にそれを最後に追加されたデータ構造からのデータを、出てきます。全体のプロセスは、データが更新される前に、データを読むための他のコードを持っていない、原子を実行する必要があります。明らかに、保護するためのロック-シンプルなアトミック操作は、より複雑な同期メソッドを使用する必要が何かを、行うことはできません
  • Linuxのカーネルは、最も一般的なロックスピンロック(スピンロック)ですスピンロックは唯一の実行可能なスレッド保持の最大ことができます。
    • しようとしている実行のスレッド場合を手に入れるには(いわゆる競合)スピンロックされている場合、スレッドは常に、再利用可能なため回転ロック待ちを循環忙しくなります
    • 競合をロックしない場合は、ロック要求の実行スレッドはすぐにそれを得ることができます継続します
  • いつでも、クリティカルセクションに入るながらスピンロックは、実行の複数のスレッドを防ぐことができますすべてのデータに対して所定のアクセスを保護および同期することができるため、同じロックは、例えば、複数の位置で使用することができます

非スピンとスピン

  • スピンロック:
    • スピンロック競合は、そのスレッドが要求するようなものであるロックが利用可能になるのを待っている間に(特に廃棄物処理時間で)スピンを、この現象は、スピンロック点です。だから、スピンロックを長時間保持するべきではありません軽量短期間でロックされていた。実際には、これはスピンロックを使用しての本来の意図とは何か
  • 非スピンロック:
    • また、ロックとの戦いに対処するための別の方法をとることができます。ロックが使用可能になるまで、その後再びそれを目覚め、睡眠に要求スレッドを作ります。プロセッササイクルあなたは待つ必要はありませんので、あなたは他のコードを実行するために行くことができます
    • これも、いくつかのオーバーヘッドをもたらすでしょう- 二つの異なるコンテキストスイッチがあり、スピンロックを達成するためにスワップアウトにスレッドをブロックし、降伏し、数行のコードと比較して、当然のことながら、より多くのコンテキストスイッチを持っていますコード。このように、時間は、好ましくは、スピンロック時間のかかる二回のコンテキストスイッチを完了することを保持するよりもありますもちろん、私たちのほとんどは、時間がかかり、我々は時間のスピンロックを保持しているが、それにはできるだけ短くする必要がありましょうので、コンテキストスイッチを測定することを無駄にしません
  • 私たちは、ほとんどの信号について説明します以下のページでは、彼は競合のイベントを行い、上記第2のロックメカニズムを提供し、待機中のスレッドをスリープ状態に置くのではなく、回転することができます

第二に、スピンロックの方法

  • 密接に実装およびアーキテクチャスピンロックに関連し、コードが頻繁にコンパイルすることによって達成されますこれらのアーキテクチャのコードに関連する定義ファイルの<ASM / spinlock.h>、使用する実際の必要性に定義されたインタフェースをは<linux / spinlock.h>内のファイル
  • 次のようにスピンロックを使用して、基本的な形式は次のとおりです。

  • そのスレッドの実行によって、アップ保有同時にスピンロック、以来、タイムクリティカルなエリアに1つのだけのスレッドのマルチプロセッサマシンを防ぐために必要な保護メカニズムへの同時アクセスを提供し、。ことを注意し、単一プロセッサマシン、コンパイル時にスピンロックに参加しませんそれが唯一のカーネルプリエンプションメカニズムが有効になっているかどうかをセットスイッチとしてあります。あなた無効にカーネルプリエンプション場合は、コンパイル時にスピンロックは完全にカーネルのうちに削除されます

警告:スピンロックは再帰的ではありません

  • Linuxカーネルの実装のスピンロックは、他のオペレーティングシステムでのスピンロックから、この異なっを達成するために、再帰的ではありません。あなたが保持しているロックを取得しようとしているのであれば、あなたがロックを解除するのを待っている、スピンを持っています。あなたがロックを解除する機会を持っていることはありませんので、しかし、あなたは、あなた自身がロックアップしている、ビジーウェイトスピンにしています。慎重なスピンロック

割り込みハンドラでのスピンロック

  • あなたは、割り込みハンドラ内で(彼らは睡眠につながるので、セマフォは、ここで使用することはできません)スピンロックを使用することができます。では、ハンドラ割り込みスピンロックを使用し、ロックの前に使うようにしてください、最初の無効化ローカル割り込み(要求割り込み、現在のプロセッサ上で)、それ以外の場合は、割り込みハンドラは、カーネルコードがロックを保持している中断されますこれは、スピンロックを開催されていると競争することがしようとします。その結果、割り込みハンドラは、ロックが使用可能になるのを待ってスピンしますが、割り込みハンドラが終了する前に、ロックホルダは実行できません。これは、私たちがコンテンツ要求ダブルデッドロックで先に述べたものです。現在のプロセッサ上でのみ中断を閉鎖することの必要性に注意してください。割り込みは、(異なるプロセッサ上で)同じスピンロックの割り込みハンドラは、それが最終リリースロックロックホルダに干渉しない場合でも、異なるプロセッサ上で発生した場合
  • 割り込みは、同じ時にカーネルによってロック要求インタフェースを提供し、次のように、簡単に使用します:
    • spin_lock_irqsave():この関数は、割り込みの現在の状態を保存し、無効ローカル割り込み、その後、指定されたロックを取りに行きます
    • spin_unlock_irqrestore():指定されたロックは、ロックを解除して、ロック前の状態に復元中断させています
    • 割り込みが最初に禁止された場合でもので、コード誤ってそれらを活性化しないが、逆に、我々は彼らを禁止させていきます
    • これらのロック機能の一部ので、などルックによって渡されるフラグ変数の値は、マクロの方法によって達成されます

  • シングルプロセッサシステムでは、ものの、ロック機構は、コンパイル時に破棄、それでも、割り込み上に共有データへのアクセスを禁止する割り込みハンドラを例を閉じる必要があります。それぞれ、ロックとロック解除、無効になると、カーネルプリエンプションを有効にすることができます

どのようなロック?

  • ロックを使用すると、右の救済でなければならない場合には、それが標的にされなければなりません。知るためにではなくコードよりもデータを保護する必要性を重要な領域の重要性を、この章で話すの例では、保護されていますが、本当の事実は、重要なデータ領域の保護、ではないコードですが、
  • 原則:理解するプログラムを困難にして、簡単に競争条件につながるロックのコードは、正しいアプローチは、データではなく、コードロックにする必要があります
  • コードがロックされていないので、それは彼らの共有データを保護するために、特別なロックを使用する必要があります。例えば、「構造体fooがloo_lockによってロック」。あなたが共有データにアクセスする必要があるたびに、それは最初のデータが安全であることを確認する必要があります。そして、データ操作の前に、多くの場合、手段は、データのセキュリティを確保するために、まず右のロックを占領し、その後、操作を完了するためにそれを解放
  • ロックがアクティブになる前に、あなたが中断識別できる場合は、ロック解除後に以前の状態を再開する必要はありません。ロックを解除するときは、無条件で割り込みをアクティブにすることができます。この場合、使用ppin_lock_irq()とspin_unlock_irq()方が良いだろう

  • カーネルは大規模で複雑になりますので、そのため、最終的にはあなたの割り込み道路カーネルの実装に難しいことではありません把握するために、現在のコールポイントに有効です。これからこそ、我々はspin_lock_irq()メソッドの使用を促進しません。あなたはそれを使用しなければならない場合は、元の割り込みが他の人たちが非アクティブ状態でそこに着いたときにアクティブで予想される場合、非常に不幸なことができそう割り込み、アクティブになります決定する必要があります

スピンロックのデバッグ

  • コード検出手段のデバッグの数を加算したスピンロックを使用するための設定オプションのCONFIG_DEBUG_SPINLOCK。たとえば、このオプションを有効にする、カーネルが初期化されていないロックするかどうかをチェックします、それはロックされていないとき、ロックの解錠操作を行う必要があります。コードをテストする場合は、必ずこのオプションを有効にする必要があります。あなたは、さらに完全なロックをデバッグする必要がある場合は、さらにオプションのCONFIG_DEBUG_LOCK_ALLOCを開く必要があります

スピンロックの第三に、他の操作

  • あなたは、動的に作成されたスピンロックを初期化するためにspin_lock_init()メソッドを使用することができます(この時点では、ポインタspinlock_tの一種類のみを持っている、それは実体ではありません)
  • spin_try_lock()ロックが競合している場合は、この方法は、スピンロックが解除されるのを待たずに、すぐにゼロ以外の値を返し、特定のスピンロックを取得しようと、スピンを得ることに成功した場合ロックは、この関数は0を返します。同様に、spin_is_locked()メソッドは、特定のロックが現在占有されているかどうかを確認するために使用される既に占有場合、非ゼロを返し、そうでなければゼロ。決意の方法だけで、実際のない占有
  • 次の図は、標準のスピンロック操作の完全なリストを表示します

第四に、かつ低スピンロック

  • 私は下半分と併せて使用前の記事で述べたように、ケアは、ロック機構を使用するように注意する必要があります。機能spin_lock_bhは()指定されたロックを取得するために使用され、そしてそれは、すべての下半分の実装を禁止します。spin_unlock_bh()関数に対応する逆の動作を行います
  • 原因コードの下半分にプロセスコンテキスト共有データの下側部分が場合ように、プロセスのコンテキストをつかむことができ、共有データは、プロセスコンテキストに保護されなければならない、下半分にロックする必要があり、実行を禁止します同様に、割り込みハンドラは、割り込みハンドラと下位共有データならばそう、あなたも同時に無効に割り込みが右のロックを取得する必要があり、下半分を先取りすることができますので、
  • ことを思い出して同様のタスクレットを同時に実行することはできませんが、その同じタスクレットでデータを共有するための保護を必要としませんデータはタスクレットの2種類で共有されている場合でも、我々は下半分にデータにアクセスする前に、通常のスピンロックを取得する必要があります。同じプロセッサ上でタスクレットの発作の別の場合があることは決してありませんので、必要は下半分を禁止していないがあります
  • データはソフト割り込み共有している場合ソフト割り込みの場合は、同じタイプかどうか、それはロックを保護する必要があります2つのソフト割り込みの同じタイプは、システム内の複数のプロセッサ上で同時に実行することができたとしても、これはあります。ただし、同じプロセッサ上のソフトカットオフは別のソフト割り込みを先取りしませんので、下半分を禁止する必要はありません

第五に、読み書きスピンロック

  • 時には、ロックは明らかに2つのシーンを読み書きするために使用に分けることができます。例えば、可能なだけでなく、必要なのリストは、検索更新します。更新(書き込み)チェーンは、書き込みやリストからデータリストを読み、同時に他のコードを持つことができない場合は、書き込み動作が完全に排他が必要です。プログラムはオンライン上の他の書き込みが表示されません。一方、時に限り、(読み取り)のリストを取得します。限り何も書き込み操作がないので、複数の同時読み取り操作は安全です。タスクリストのアクセスパターンがこのような場合に非常に似ている、それが読み書きスピンロックにより保護されています
  • 使用読み取り/書き込み方法は、以下の方法で初期化されている通常のスピンロックスピンロック、次のようになります。

  • その後、支店のコードリーダーで、以下の機能を使用します:

  • 最後に、中にあなたのコードの分岐ライターで次の関数を使用します。

  • 典型的には、読み取りおよび書き込みロックは、図に示す例のように、完全に分離されたビット・コード・ブランチを乾燥します。
  • 注意、あなたは書き込みロックに「アップグレード」の読み取りロックをかけることはできません。たとえば、次のコードを考えてみます。

  • 書き込みロックは、すべての読者は、独自含めて、ロックを解除するのを待っている、スピンしていきますので、これらの2つの関数の実装は、デッドロックにつながります。書き込みに必要な操作を行うときに、先頭のリクエストに応じてロックを書き込みます。あなたが読むことができないと書き込みが明確に分離した場合、その行の一般的なスピンロックの使用は、読み書きスピンロックを使用しないでください
  • 読者にもスレッドが再帰的に同じ読み取りロックが安全で取得するには、実際には、読み取りロックをより安全に得ることができます。この機能は、読み書きスピンロックが本当に有用で、一般的に使用される最適化手法となります。あなたが唯一の書き込み操作なしで割り込みハンドラを読めば、あなたは(「割り込み禁止」ロック、使用read_lockを混在させることができます)の代わりに(read_lock_irqsave)保護をお読みください。しかし、あなたはまだ使用write_lock_irqsave()割り込み禁止書き込み動作に必要な、そうでない場合は、読み出し動作の中断は書き込みロックでロックする可能性があります
  • インデックスは、スピンロックのすべての読み取りおよび書き込み操作を示しています

  • Linuxの読み書きスピンロックを使用する場合は、考慮すべき最後の点は、ロック機構はもう少し気を書くことよりも、読むために世話をするということです。ロックは、読み取りおよび書き込み操作のみの排他的アクセスを待つことができます保持されている場合は、しかし、読者はそれがロックを保持するために成功し続けることができます。ロックがロックを取得することはできませんすべての読者が解除されるまで、ライター・スピンが待ちます。そのような行動が有益である場合がありますが、時にはそれが災害をもたらすだろう - そのため、読者の大多数は、あなた自身のロックを設計するとき、飢えている保留中の書き込みはこのことを忘れてはならないしなければなりません
  • 自旋锁提供了一种快速简单的锁实现方法。如果加锁时间不长并且代码不会睡眠(比如中断处理程序),利用自旋锁是最佳选择。如果加锁时间可能很长或者代码在持有锁时有可能睡眠, 那么最好使用信号量来完成加锁功能
发布了1360 篇原创文章 · 获赞 909 · 访问量 26万+

おすすめ

転載: blog.csdn.net/qq_41453285/article/details/104083379