専門用語を使わない探究心で解明する
私たちはしばしば、完全に理解していない用語やフレーズを耳にし、学び、そして使用することがあります。 これは、RESTful Web API、アジャイル方法論、機械学習、またはその他の用語であろうと、ソフトウェア開発コミュニティではかなり一般的なことだと思います。 これは必ずしも悪いことではありませんが、何かを本当に知っているときと、その名前を知っているだけのときを理解することが重要です。
私にとっては、システム プログラミングがそのような用語の1つです。
システムズ・プログラミングが何を意味するのかを理解する前に、まず、システムとは何かを理解する必要があります。 ソフトウェアは、システム・ソフトウェアとアプリケーション・ソフトウェアの2つに分類される傾向があります。
システム・ソフトウェアとは、他のソフトウェアにプラットフォームを提供するために設計されたコンピュータ・ソフトウェアです。 システムソフトウェアの例としては、オペレーティングシステム、計算科学ソフトウェア、ゲームエンジン、産業オートメーション、SaaSアプリケーションなどがある。
… 他のソフトウェアの機能に影響を与えずに通常アンインストールできる場合、そのようなソフトウェアはシステムソフトウェアとはみなされない。
– wikipedia.orgシステムソフトウェアは、設定やプリファレンス、ファイルライブラリ、システムアプリケーションに使用する機能などのオペレーティングシステム (OS) プログラムとサービスからなるプラットフォームである。
– techopedia.comシステム ソフトウェアは、コンピュータのオペレーティング システムを構成するファイルおよびプログラムを指します。 システム ファイルには、関数のライブラリ、システム サービス、プリンターやその他のハードウェアのドライバー、システム環境設定、およびその他の設定ファイルが含まれます。 システム ソフトウェアの一部であるプログラムには、アセンブラ、コンパイラ、ファイル管理ツール、システム ユーティリティ、およびデバッガが含まれます。
– techterms.com
Wikipedia の定義は、他のアプリケーションにサービスを提供する限り、何がシステム ソフトウェアとみなされるかについて非常に曖昧です。 しかし、他の 2 つの定義では、ドライバ、カーネル、ライブラリ、関数 (カーネル/libc ヘッダーファイルと共有オブジェクトを考えてください) など、純粋にオペレーティング システムに焦点が当てられています。 これは、ハードウェアと密接な関係があることを意味します。 システム プログラミングに関する別の Wikipedia の記事を見てみると、次のように書かれています:
System programming requires a great degree of hardware awareness.
この記事は、システム プログラミングの中核部分は、非常に高速でなければならないことを示唆しています。 このことは、ハードウェアについて多くのことを知る必要がある理由を納得させてくれます。 また、他のソフトウェアへのプラットフォームである場合、速度 (パフォーマンス) がシステム プログラミングの中核部分であることも理解できます。
アプリケーションの最も中心的な部分 (システム ソフトウェア「プラットフォーム」) が遅い場合、アプリケーション全体も遅くなります。 多くのアプリケーション、特に大規模なアプリケーションでは、これは破格のことです。
System Software in a Nutshell
上記の引用やその他のリソースから、システム ソフトウェアを定義する基準として、次のものが導き出されました。
What is and What isn’t System Software
システム ソフトウェアの例:
- OS カーネル
- Driver
- Bare Metal Hypervisors (e.g.), (b.)。g. Hyper-V および VM Ware ESXi)
- Compiler (ネイティブ バイナリを生成) および Debugger
システム ソフトウェアでないものの例です。
- GUI チャット アプリケーション (Slack、Discord など)
- Web ベースの JavaScript アプリケーション
- Web サービス API
他のソフトウェアにサービスを提供しますが、ハードウェアに対する抽象化を公開するために(通常は)ハードウェアと対話しないことに気づかれることでしょう。 しかし、中間のグレーゾーンに該当するアプリケーションもあります。 証券取引所でのリアルタイム取引などのハイパフォーマンス コンピューティング (HPC) アプリケーションは、通常、プラットフォームを公開しませんが、ハードウェアと直接インターフェイスするコードを記述することは一般的です。 たとえば、カーネルが提供するネットワーク スタックをバイパスして、NIC と直接通信する独自のネットワーク スタックを実装することができます。 このように、HPC ソフトウェアは、必要なパフォーマンス向上を提供するためにハードウェアと直接対話することにより、システム ソフトウェアと多くの類似点を共有していることがわかります。 しかし、提供される抽象化は、通常、同じソフトウェアによって消費され、プラットフォームとはみなされません。
システム ソフトウェアの定義と類似しているアプリケーションに注意することは重要です。)
システム プログラミング (+ 言語)
システムを定義したら、システム プログラミングとはシステム プログラミング言語を用いてシステムソフトウェアを作る行為と定義することができます。 簡単でしょう?
さて、ここでひとつ、言語というものを飛ばしてしまいました。 人々はしばしば、「X は素晴らしく、高速で、コンパイル可能で、システム・プログラミング言語である」というような形でシステム・プログラミング言語について話します。 しかし、システム プログラミング言語が何であるかについて、誰もが同じ考えを持っているでしょうか。
システムについての定義を考えると、私はシステム プログラミング言語の基準を次のように定義します:
- ネイティブ バイナリへのコンパイル
- 他のソフトウェアに依存せずに構築可能(カーネルも含む)
- 他のシステム プログラム言語と同様のパフォーマンス特性
注意:これは私の定義です。
Compile to Native Binary
CPU が直接解釈できる実行ファイルにコンパイルできない言語は、定義により、プラットフォーム (例: JVM、Ruby VM、Python VM、など) で実行されているものとします。 しかし、単純化するために、私はこれが適切な基準だと思います。
No Dependencies
この議論は、ネイティブ バイナリにコンパイルする場合と似ています。 もし言語が実行するために他のソフトウェアが常に存在することを必要とするならば、それはプラットフォーム上で実行されていることになります。 この例として、Go とそれに含まれる標準ライブラリがあります。 Goは、メモリの確保、(ゴルーチン実行用の)スレッドの生成、組み込みのネットワークポーラなどの基本的な動作を行うために、OSからのサポートを必要とします。 これらのコア機能を再実装することは可能ですが、このコンテキストで使用するには障壁があり、すべての言語、たとえ静的バイナリにコンパイルできる言語であっても、システム プログラミング言語として意図されていない理由は容易に想像できます。 しかし、システム プログラミング言語として一般的に分類される言語のシステムの中では、パフォーマンス特性に大きな(桁違いの)違いがあってはならないということを言いたいのです。
比較のための黄金律は C や C++ で、これはしばしば比較ベンチマークに表されますが、C/C++ より何桁遅いかで実行速度を測定しています。 しかし、Rust や Nim のような新しい言語も、このニッチを満たしています。 実際、完全に Rust で書かれた OS (RedoxOS) や、Nim (nimkernel) のカーネルがすでにあります。
Let’s Talk About Go
先に、Go が「システム プログラミング言語」のファミリに該当しないかもしれないという事実をほのめかしました。 しかし、すべてのアプリケーションがアプリケーション ソフトウェアとシステム ソフトウェアにうまく分類されないのと同様に、言語もそうではありません。
しばしば人々は Go をシステム プログラミング言語と呼び、golang.org でも次のように引用されています:
Go is a general-purpose language designed with systems programming in mind.
しかしこれは Go がシステム プログラミング言語だと明確に主張しているわけではなく、単に念頭に置いて設計されていると述べています。 Go はネイティブ バイナリにコンパイルでき、有用な低レベルのコンセプト (raw/unsafe ポインタ、bytes や int32 などのネイティブ型、インライン アセンブリ サポート) を含み、比較的高性能ですが、克服すべき課題もあります。 Go にはランタイムとガベージコレクタが付属しています。
ランタイムは、カーネルのない環境で実行するには、ランタイムのブートストラップ/オーバーライドが必要であることを意味します。 これは言語の内部実装により深く入り込んでおり、将来のリリースでは変更される可能性があります。 ガベージコレクター (GC) は、Go が使用できるアプリケーション領域が制限されているか、GC を無効にして手動メモリ管理に置き換えなければならないことを意味します。 GC を置き換えることができない場合、リアルタイム領域 (与えられた時間境界内で完了する必要がある、またはパフォーマンスがナノ秒単位で測定される操作によって定義される) は、GC の非決定的な一時停止時間のリスクを冒すことができないでしょう。
この時点まで、システム プログラミングやシステム エンジニアという用語が、本当の意味は分散システム プログラミングや分散システム エンジニアであるという文脈で使われているのを目にしてきました。 しかし、分散システムについて語るとき、システムの意味は変わってきます。 具体的な違いについてここで深く掘り下げるつもりはありませんが (主に、私自身がまだよく理解する必要があるため)、まだこの分野を学んでいる人たちが混乱しないように、精神的な区別を行い、可能な場合はより正確な言葉を使用することが重要です。