ハードウェア抽象化とは、ハードウェアへのアクセスを提供するソフトウェアであり、ハードウェアの使用を困難にする可能性のある詳細を隠蔽するものです。通常、アクセスはソフトウェアインターフェースを介して提供され、異なるハードウェアインターフェースを提供するデバイスであっても、類似性を持つデバイスには同じソフトウェア操作でアクセスできるようになります。ハードウェア抽象化は、クロスプラットフォームアプリケーションの開発をサポートします。
初期のソフトウェアはハードウェア抽象化なしで開発されていたため、開発者は互換性を確保するために複数のデバイスを理解する必要がありました。ハードウェア抽象化を用いることで、ソフトウェアは抽象化を利用して、同じインターフェースを介して大きく異なるハードウェアにアクセスできるようになります。そして、この抽象化(多くの場合、オペレーティングシステムに実装されている)がハードウェア固有の操作を実行します。これにより、ソフトウェアは抽象化によってサポートされるすべてのデバイスと互換性を持つことができます。
ジョイスティックデバイスを考えてみましょう。ジョイスティックには多くの物理的な実装が存在します。これは、移動、発射、感度設定など、さまざまなジョイスティック間で共通の操作をサポートするアプリケーションプログラミングインターフェース(API)を介してアクセスできます。ジョイスティック抽象化は詳細(レジスタフォーマット、 I2Cアドレスなど)を隠蔽するため、抽象化を使用するプログラマはデバイスの物理インターフェースに関する詳細を理解する必要がありません。これにより、同じコードでジョイスティック抽象化を提供するあらゆる種類の実装からの標準化されたメッセージを処理できるため、コードの再利用も可能になります。たとえば、「前方に軽く押す」動作は、ポテンショメータからでも、「スワイプ」ジェスチャーを認識する静電容量式タッチセンサーからでも構いません。どちらも「移動」に関連する信号を提供する限り、どちらも有効です。
ハードウェアによって物理的な制約が異なる場合があるため、API は「最小公倍数」モデルを仮定する以外に、その制約を隠蔽する手段はほとんどありません。したがって、実装における特定のアーキテクチャ上の決定事項が、抽象化の特定のインスタンスを使用するユーザーにとって重要になる可能性があります。
良い比喩として、交通手段の抽象化が挙げられます。自転車に乗ることも、車を運転することも、どちらも交通手段です。両者には共通点(例えば、操縦する必要があること)と物理的な相違点(例えば、動力源)があります。「目的地まで運転する」という抽象化を常に指定し、自転車に乗るか車を運転するかは実装者に判断を委ねることができます。「車輪付きの陸上輸送」という機能は抽象化され、「運転方法」の詳細はカプセル化されます。
高水準プログラミング言語は、プログラマが中央処理装置(CPU)やその命令セットアーキテクチャ(ISA)(CPUの基本操作)に固有の命令を使用せずにアルゴリズムを記述できるようにすることで、ハードウェアの抽象化を実現します。例えば、コンパイラは特定のISAに対応するCPU固有の命令を生成します。このようにして、ソースコードは複数のプラットフォーム間で移植性を確保できます。
ハードウェア抽象化レイヤー(HAL)は、コンピュータの物理ハードウェアと、そのコンピュータ上で動作するソフトウェアとの間に、ソフトウェアで実装された抽象化レイヤーです。その機能は、オペレーティングシステムのカーネルの大部分からハードウェアの違いを隠蔽することであり、これにより、カーネルモードのコードの大部分は、異なるハードウェア構成のシステム上で動作するように変更する必要がなくなります。Microsoft Windowsでは、HALは基本的にマザーボードのドライバとみなすことができ、上位レベルのプログラミング言語からの命令が下位レベルのコンポーネントと通信することを可能にしますが、ハードウェアへの直接アクセスは防止します。
CP/M ( CP/M BIOS )、DOS ( DOS BIOS )、Solaris、Linux、BSD、macOS、およびその他のポータブルなオペレーティングシステムにも、明示的に HAL として指定されていなくても HAL があります。Linux などの一部のオペレーティングシステムは、Adeos のように実行中に HAL を挿入する機能があります。NetBSDオペレーティングシステムは、クリーンなハードウェア抽象化レイヤーを備えていることで広く知られており、これにより高い移植性を実現しています。[ 1 ]このシステムの一部として、/ 、、 、およびその他のサブシステムがあります。ISA 、EISA、PCI、PCIeなど、複数のアーキテクチャで使用される一般的なバスも抽象化されており、最小限のコード変更でドライバも高い移植性を実現しています。
HAL(ハードウェア抽象化レイヤー)が明確に定義されたオペレーティングシステムは、異なるハードウェア間での移植性が向上します。これは、数十種類の異なるプラットフォームで動作する組み込みシステムにとって特に重要です。
ソフトウェアスタックにおいて、HAL(ハードウェア抽象化レイヤー)はアプリケーションプログラミングインターフェース(API)の下に位置し、アプリケーションレイヤー(多くの場合、高水準言語で記述される)はAPIの上に位置し、API内の関数を呼び出すことによってハードウェアと通信する。

Windows NTカーネルには、ハードウェアと実行サービスの間のカーネル空間に HAL があり、これは[ 2 ] [ 3 ]の にあります。これにより、Windows NT カーネルモード コードをさまざまなプロセッサ、さまざまなメモリ管理ユニットアーキテクチャ、さまざまな I/O バス アーキテクチャを持つさまざまなシステムに移植できます。これらのシステムに適用可能な命令セット用にコンパイルすると、ほとんどのコードはこれらのシステムで変更せずに実行されます。たとえば、SGI Intel x86 ベースのワークステーションはIBM PC 互換ワークステーションではありませんでしたが、HAL のおかげで、Windows 2000はこれらのワークステーションで実行できました。[ 4 ] Windows VistaおよびWindows Server 2008以降、使用される HAL は起動時に自動的に決定されます。実際、 Windows Vista以降、Windows NT はACPIベースの HALのみを許可しています。[ 5 ]ntoskrnl.exehal.dll
Windows CE には、 OEM Adaptation Layer (OAL)と呼ばれる HAL もあり、これは または にコンパイルされoal.exe、oal.dllブートnk.binイメージに含まれています。
Windows 9xでは、実際のカーネルと実際の HAL の両方が ですvmm32.vxd。
HAL の「極端な」例は、現在IBM iオペレーティング システムで実装されているSystem/38およびAS/400アーキテクチャに見られます。これらのシステムのほとんどのコンパイラは抽象マシン コードを生成します。ライセンス内部コード (LIC) は、この仮想マシン コードを実行中のプロセッサのネイティブ コードに変換し、生成されたネイティブ コードを実行します。[ 6 ] (例外は LIC 自体を生成するコンパイラです。これらのコンパイラは IBM 以外では入手できません。) これは非常に成功したため、オリジナルの S/38 でコンパイルされた LIC レイヤーより上のアプリケーション ソフトウェアとオペレーティング システム ソフトウェアは、基盤となるハードウェアが大幅に変更され、少なくとも 3 種類の異なるプロセッサが使用されているにもかかわらず、最新の AS/400 システムで修正や再コンパイルなしで実行できます。[ 6 ]
Android はバージョン 8.0「Oreo」で「ベンダー インターフェース」(コードネーム「Project Treble」)と呼ばれる HAL を導入しました。これは Android OS フレームワークから低レベルのコードを抽象化し、ファームウェア アップデートの開発を容易にするために将来の Android バージョンをサポートするために前方互換性を持たせる必要があります。[ 7 ] Project Treble 以前は、Android はさまざまな非標準化されたレガシー HAL に依存していました。[ 8 ]
HaliumはAndroidベースのHALであり、Ubuntu TouchやLuneOSなど、Androidがプリインストールされたスマートフォン上で動作するために、いくつかのモバイルオペレーティングシステムで使用されています。