Linux カーネルのメモリバリアの詳細な説明
######序文######
以前、逐次一貫性とキャッシュ一貫性に関するディスカッション記事を読み、これら 2 つの概念の違いと関連性をより明確に理解しました。 Linux カーネルには、多くの同期およびバリア メカニズムが存在します。ここでは、それらについて要約したいと思います。
キャッシュの一貫性
以前は、Linux の多くのメカニズムはキャッシュの一貫性を確保するためのものだと常々思っていましたが、実際には、キャッシュの一貫性のほとんどはハードウェア メカニズムによって実現されています。ロック接頭辞を持つ命令を使用する場合にのみ、キャッシュに関係します (これは厳密ではありませんが、現在の観点から見ると、ほとんどの場合に当てはまります)。ほとんどの場合、私たちは逐次一貫性を確保したいと考えています。 キャッシュの一貫性とは、マルチプロセッサ システムでは、各 CPU が独自の L1 キャッシュを持つことを意味します。同じメモリの内容が異なる CPU の L1 キャッシュにキャッシュされる可能性があるため、CPU がキャッシュされた内容を変更する場合、このデータを読み取るときに別の CPU も最新の内容を読み取ることができるようにする必要があります。ただし、この複雑な作業はハードウェアによって完全に実行されるので、心配しないでください。MESI プロトコルを実装することで、ハードウェアはキャッシュ コヒーレンシ作業を簡単に完了できます。複数のCPUが同時に書き込みをしても問題ありません。 CPU は、自身のキャッシュ、他の CPU のキャッシュ、メモリのいずれに存在しても、常に最新のデータを読み取ることができ、これがキャッシュの一貫性の仕組みです。
シーケンシャル一貫性いわゆる順次一貫性は、キャッシュ一貫性とはまったく異なる概念を指しますが、どちらもプロセッサ開発の成果物です。コンパイラ テクノロジは進化し続けるため、コードを最適化するために特定の操作の順序が変更される場合があります。マルチイシューとアウトオブオーダー実行の概念は、プロセッサーに長い間存在していました。その結果、実際に実行される命令の順序は、プログラミング中のコードの実行順序とわずかに異なります。もちろん、これは単一のプロセッサの下では何も起こりません。結局のところ、自分のコードが通過しない限り、誰も気にしません。コンパイラとプロセッサは、自分のコードが発見されないようにしながら、実行順序を混乱させます。しかし、マルチプロセッサの場合はそうではなく、あるプロセッサで命令が完了する順序は、他のプロセッサで実行されるコードに大きな影響を与える可能性があります。したがって、あるプロセッサ上のスレッドの実行順序が、他のプロセッサ上のスレッドの観点から同じであることを保証する、逐次一貫性の概念があります。この問題を解決するには、プロセッサまたはコンパイラだけでは解決できず、ソフトウェアの介入が必要です。 記憶の壁
ソフトウェア介入の方法も非常に簡単で、メモリバリアを挿入するだけです。実際、メモリバリアという用語はプロセッサ開発者によって作られたものであり、私たちにとっては理解しにくいものです。メモリバリアにより、キャッシュの一貫性が簡単に失われる可能性があり、変更されたキャッシュを他の CPU が参照できるようにすることができるかどうかすら疑問になりますが、そう考えるのは間違いです。いわゆるメモリ バリアは、プロセッサの観点から見ると、読み取りおよび書き込み操作をシリアル化するために使用され、ソフトウェアの観点から見ると、逐次一貫性の問題を解決するために使用されます。コンパイラは、コードの実行順序を乱したくないのでしょうか? プロセッサは、コードを順序どおりに実行したくないのでしょうか? メモリ バリアを挿入することは、コンパイラに命令の前後の順序を変更するように指示することと同じです。バリアは元に戻すことはできません。プロセッサに対して、バリアの前の命令のみを待機できるように指示します。命令が実行された後、バリアの後ろの命令の実行を開始できます。もちろん、メモリの障壁によってコンパイラの混乱を防ぐことはできますが、プロセッサにはまだ解決策があります。プロセッサには、複数発行、アウトオブオーダー実行、およびシーケンシャル完了という概念はありませんか? メモリ バリア中は、前の命令の読み取りおよび書き込み操作が、プロセッサが実行される前に完了していることを確認するだけで十分です。次の命令の読み取りおよび書き込み操作が完了します。したがって、メモリ バリアには、読み取りバリア、書き込みバリア、読み取り/書き込みバリアの 3 種類があります。たとえば、x86 より前では、書き込み操作は順序どおりに完了することが保証されていたため、書き込みバリアは必要ありませんでしたが、一部の ia32 プロセッサでは、書き込み操作が順序どおりに完了しないため、書き込みバリアも必要になりました。
実際、特殊な読み書きバリア命令に加えて、ロック プレフィックスを持つ命令など、読み書きバリア機能を使用して実行される命令が多数あります。特殊な読み取りおよび書き込みバリア命令が登場するまで、Linux はロックに依存して生き残っていました。
読み取りおよび書き込みバリアをどこに挿入するかについては、ソフトウェアのニーズによって異なります。読み取り/書き込みバリアは逐次一貫性を完全に達成することはできませんが、マルチプロセッサ上のスレッドは実行順序を常に監視しているわけではありません。監視するときに逐次一貫性が遵守されていると判断される限り、スレッドは実行順序を監視します。実行によってコードに予期しない状況が発生することはありません。いわゆる予期せぬ状況、たとえば、スレッドが最初に変数 a に値を割り当て、次に変数 b に値を割り当てます。その結果、他のプロセッサで実行されているスレッドが調べて、b に値が割り当てられていることがわかります。しかし、 a には値が割り当てられていません (注: この不一致はキャッシュの不一致が原因ではなく、プロセッサの書き込み操作が完了する順序の不一致によって引き起こされます)。この場合、割り当てと割り当ての間に書き込みバリアを追加する必要があります。 a と b の代入。
プロセッサ間の同期
SMP を使用すると、スレッドは複数のプロセッサ上で同時に実行を開始します。スレッドである限り、通信と同期の要件が存在します。幸いなことに、SMP システムは共有メモリを使用するため、すべてのプロセッサが同じメモリ内容を認識します。独立した L1 キャッシュがありますが、キャッシュの整合性処理は依然としてハードウェアによって処理されます。異なるプロセッサ上のスレッドが同じデータにアクセスしたい場合は、クリティカル セクションと同期が必要です。同期は何に依存しますか?以前の UP システムでは、上部ではセマフォに依存し、下部では割り込みと読み取り、変更、書き込み命令をオフにしていました。現在、SMP システムでは割り込みをオフにする機能は廃止されており、同じプロセッサ上のスレッドを同期する必要があることに変わりはありませんが、それだけに頼るだけでは十分ではなくなりました。読み取り変更書き込み命令?もうない。命令内の読み取り操作が完了し、書き込み操作が実行されていない場合、別のプロセッサーが読み取り操作または書き込み操作を実行する可能性があります。キャッシュ コヒーレンス プロトコルは進歩していますが、どの命令がこの読み取り操作を発行したかを予測できるほどまだ進歩していません。そこで、x86 はロック プレフィックスを伴う命令を発明しました。この命令が実行されると、命令内の読み取りおよび書き込みアドレスを含むすべてのキャッシュ ラインが無効になり、メモリ バスがロックされます。このように、他のプロセッサが同じアドレスまたは同じキャッシュ ライン上のアドレスを読み書きしたい場合、キャッシュから実行することも (キャッシュ内の関連するラインの有効期限が切れている)、キャッシュから実行することもできません。メモリ バス (メモリ バス全体に障害が発生しました)、ロックされています)、最終的にアトミック実行の目標を達成します。もちろん、P6 プロセッサ以降では、ロック プレフィックス命令でアクセスするアドレスがすでにキャッシュ内にある場合、メモリ バスをロックする必要はなく、アトミック操作を完了できます (これはおそらく、マルチプロセッサの内部共通機能の追加) L2キャッシュのため)
メモリ バスがロックされるため、未完了の読み取りおよび書き込み操作は、ロック プレフィックスが付いた命令が実行される前に完了し、メモリ バリアとしても機能します。
現在、マルチプロセッサ間のスレッドの同期には、上部でスピン ロックが使用され、下部でロック プレフィックスを使用した読み取り、変更、書き込み命令が使用されます。もちろん、実際の同期には、プロセッサのタスク スケジューリングの無効化、タスクオフ割り込みの追加、外部セマフォの追加も含まれます。 Linux でのこの種のスピン ロックの実装は 4 世代にわたる開発を経て、より効率的かつ強力になりました。
内存屏障的实现
\#ifdef CONFIG_SMP
\#define smp_mb() mb()
\#define smp_rmb() rmb()
\#define smp_wmb() wmb()
\#else
\#define smp_mb() barrier()
\#define smp_rmb() barrier()
\#define smp_wmb() barrier()
\#endif
CONFIG_SMP就是用来支持多处理器的。如果是UP(uniprocessor)系统,就会翻译成barrier()。
#define barrier() asm volatile(“”: : :”memory”)
barrier()的作用,就是告诉编译器,内存的变量值都改变了,之前存在寄存器里的变量副本无效,要访问变量还需再访问内存。这样做足以满足UP中所有的内存屏障。
\#ifdef CONFIG_X86_32
/*
\* Some non-Intel clones support out of order store. wmb() ceases to be a
\* nop for these.
*/
\#define mb() alternative("lock; addl $0,0(%%esp)", "mfence", X86_FEATURE_XMM2)
\#define rmb() alternative("lock; addl $0,0(%%esp)", "lfence", X86_FEATURE_XMM2)
\#define wmb() alternative("lock; addl $0,0(%%esp)", "sfence", X86_FEATURE_XMM)
\#else
\#define mb() asm volatile("mfence":::"memory")
\#define rmb() asm volatile("lfence":::"memory")
\#define wmb() asm volatile("sfence" ::: "memory")
\#endif
如果是SMP系统,内存屏障就会翻译成对应的mb()、rmb()和wmb()。这里CONFIG_X86_32的意思是说这是一个32位x86系统,否则就是64位的x86系统。现在的linux内核将32位x86和64位x86融合在同一个x86目录,所以需要增加这个配置选项。
可以看到,如果是64位x86,肯定有mfence、lfence和sfence三条指令,而32位的x86系统则不一定,所以需要进一步查看cpu是否支持这三条新的指令,不行则用加锁的方式来增加内存屏障。
SFENCE,LFENCE,MFENCE指令提供了高效的方式来保证读写内存的排序,这种操作发生在产生弱排序数据的程序和读取这个数据的程序之间。
SFENCE——串行化发生在SFENCE指令之前的写操作但是不影响读操作。
LFENCE——串行化发生在SFENCE指令之前的读操作但是不影响写操作。
MFENCE——串行化发生在MFENCE指令之前的读写操作。
sfence:在sfence指令前的写操作当必须在sfence指令后的写操作前完成。
lfence:在lfence指令前的读操作当必须在lfence指令后的读操作前完成。
mfence:在mfence指令前的读写操作当必须在mfence指令后的读写操作前完成。
至于带lock的内存操作,会在锁内存总线之前,就把之前的读写操作结束,功能相当于mfence,当然执行效率上要差一些。
说起来,现在写点底层代码真不容易,既要注意SMP问题,又要注意cpu乱序读写问题,还要注意cache问题,还有设备DMA问题,等等。
多处理器间同步的实现
多处理器间同步所使用的自旋锁实现,已经有专门的文章介绍
実際、特殊な読み書きバリア命令に加えて、ロック プレフィックスを持つ命令など、読み書きバリア機能を使用して実行される命令が多数あります。特殊な読み取りおよび書き込みバリア命令が登場するまで、Linux はロックに依存して生き残っていました。
読み取りおよび書き込みバリアをどこに挿入するかについては、ソフトウェアのニーズによって異なります。読み取り/書き込みバリアは逐次一貫性を完全に達成することはできませんが、マルチプロセッサ上のスレッドは実行順序を常に監視しているわけではありません。監視するときに逐次一貫性が遵守されていると判断される限り、スレッドは実行順序を監視します。実行によってコードに予期しない状況が発生することはありません。いわゆる予期せぬ状況、たとえば、スレッドが最初に変数 a に値を割り当て、次に変数 b に値を割り当てます。その結果、他のプロセッサで実行されているスレッドが調べて、b に値が割り当てられていることがわかります。しかし、 a には値が割り当てられていません (注: この不一致はキャッシュの不一致が原因ではなく、プロセッサの書き込み操作が完了する順序の不一致によって引き起こされます)。この場合、割り当てと割り当ての間に書き込みバリアを追加する必要があります。 a と b の代入。
現在、マルチプロセッサ間のスレッドの同期には、上部でスピン ロックが使用され、下部でロック プレフィックスを使用した読み取り、変更、書き込み命令が使用されます。もちろん、実際の同期には、プロセッサのタスク スケジューリングの無効化、タスクオフ割り込みの追加、外部セマフォの追加も含まれます。 Linux でのこの種のスピン ロックの実装は 4 世代にわたる開発を経て、より効率的かつ強力になりました。
barrier()的作用,就是告诉编译器,内存的变量值都改变了,之前存在寄存器里的变量副本无效,要访问变量还需再访问内存。这样做足以满足UP中所有的内存屏障。
多处理器间同步所使用的自旋锁实现,已经有专门的文章介绍
以上がLinux カーネルのメモリバリアの詳細な説明の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。


Linuxソフトウェア分布は、各分布のエコシステムに深く染み込んでおり、DEBやRPMなどのネイティブ形式に依存していました。 ただし、フラットパックとスナップが出現し、アプリケーションパッケージへの普遍的なアプローチが約束されています。 この記事試験

デバイスドライバーの取り扱いにおけるLinuxとWindowsの違いは、主にドライバー管理と開発環境の柔軟性に反映されています。 1。Linuxはモジュラー設計を採用し、ドライバーを動的にロードしてアンインストールできます。開発者は、カーネルメカニズムを深く理解する必要があります。 2。WindowsはMicrosoftエコシステムに依存しており、ドライバーはWDKを通じて開発して署名および認定される必要があります。開発は比較的複雑ですが、システムの安定性とセキュリティを保証します。

LinuxとWindowsのセキュリティモデルには、それぞれ独自の利点があります。 Linuxは、柔軟性とカスタマイズ可能性を提供し、ユーザーの権限、ファイルシステム許可、Selinux/Apparmorを通じてセキュリティを可能にします。 Windowsはユーザーフレンドリーに焦点を当てており、WindowsDefender、UAC、Firewall、BitLockerに依存してセキュリティを確保しています。

LinuxとWindowsはハードウェアの互換性が異なります。Windowsには広範なドライバーサポートがあり、Linuxはコミュニティとベンダーに依存します。 Linux互換性の問題を解決するために、RTL818888EUドライバーリポジトリのクローニング、コンパイル、インストールなど、ドライバーを手動でコンパイルできます。 Windowsユーザーは、パフォーマンスを最適化するためにドライバーを管理する必要があります。

仮想化サポートのLinuxとWindowsの主な違いは次のとおりです。1)LinuxはKVMとXenを提供し、優れたパフォーマンスと柔軟性を備えており、高いカスタマイズ環境に適しています。 2)Windowsは、友好的なインターフェイスを備えたHyper-Vを介した仮想化をサポートし、Microsoftソフトウェアに依存する企業に適したMicrosoft Ecosystemと密接に統合されています。

Linuxシステム管理者の主なタスクには、システムの監視とパフォーマンスチューニング、ユーザー管理、ソフトウェアパッケージ管理、セキュリティ管理とバックアップ、トラブルシューティングと解像度、パフォーマンスの最適化、ベストプラクティスが含まれます。 1. TOP、HTOP、その他のツールを使用して、システムのパフォーマンスを監視し、チューニングします。 2。ユーザーADDコマンドおよびその他のコマンドを介して、ユーザーアカウントとアクセス許可を管理します。 3. APTとYUMを使用してソフトウェアパッケージを管理し、システムの更新とセキュリティを確保します。 4.ファイアウォールを構成し、ログを監視し、データバックアップを実行して、システムセキュリティを確保します。 5.ログ分析とツールの使用を通じてトラブルシューティングと解決。 6.カーネルパラメーターとアプリケーションの構成を最適化し、ベストプラクティスに従ってシステムのパフォーマンスと安定性を向上させます。

Linuxの学習は難しくありません。 1.Linuxは、UNIXに基づいたオープンソースオペレーティングシステムであり、サーバー、組み込みシステム、およびパーソナルコンピューターで広く使用されています。 2。ファイルシステムと許可管理を理解することが重要です。ファイルシステムは階層的であり、許可には読み取り、書き込み、実行が含まれます。 3。APTやDNFなどのパッケージ管理システムは、ソフトウェア管理を便利にします。 4。プロセス管理は、PSおよびTOPコマンドを通じて実装されます。 5. MKDIR、CD、Touch、Nanoなどの基本的なコマンドから学習を開始し、シェルスクリプトやテキスト処理などの高度な使用法を試してください。 6.許可問題などの一般的なエラーは、SudoとChmodを通じて解決できます。 7.パフォーマンスの最適化の提案には、HTOPを使用してリソースを監視すること、不要なファイルのクリーニング、SYの使用が含まれます


ホットAIツール

Undresser.AI Undress
リアルなヌード写真を作成する AI 搭載アプリ

AI Clothes Remover
写真から衣服を削除するオンライン AI ツール。

Undress AI Tool
脱衣画像を無料で

Clothoff.io
AI衣類リムーバー

Video Face Swap
完全無料の AI 顔交換ツールを使用して、あらゆるビデオの顔を簡単に交換できます。

人気の記事

ホットツール

SublimeText3 Linux 新バージョン
SublimeText3 Linux 最新バージョン

SublimeText3 Mac版
神レベルのコード編集ソフト(SublimeText3)

AtomエディタMac版ダウンロード
最も人気のあるオープンソースエディター

EditPlus 中国語クラック版
サイズが小さく、構文の強調表示、コード プロンプト機能はサポートされていません

ゼンドスタジオ 13.0.1
強力な PHP 統合開発環境

ホットトピック









