私はしばらくの間、オペレーティングシステムのプログラミングに興味を持っていました。いくつかの異なるサイトを調べてみると、(言い換えれば)興味深い概念に出くわしました。#includeを使用してブートローダーを書き始めた場合、すでに致命的な間違いを犯しています。
私はK&Rを経験しました、そして本全体が各レッスンを通してそれを含みます。Cの学習全体でそれを使用してきましたが、stdioを使用するものと使用しないものについて、何を学んだかわかりません。stdioなしでCで何ができますか?
私はしばらくの間、オペレーティングシステムのプログラミングに興味を持っていました。いくつかの異なるサイトを調べてみると、(言い換えれば)興味深い概念に出くわしました。#includeを使用してブートローダーを書き始めた場合、すでに致命的な間違いを犯しています。
私はK&Rを経験しました、そして本全体が各レッスンを通してそれを含みます。Cの学習全体でそれを使用してきましたが、stdioを使用するものと使用しないものについて、何を学んだかわかりません。stdioなしでCで何ができますか?
C 標準 (ISO/IEC 9899:1999) は、2 つのタイプの実装を認識しています (§4 準拠、¶6)。
フリースタンディング - 実装 (コンパイラーとライブラリー) が提供するヘッダーは 7 つだけです。
<float.h>
<iso646.h>
<limits.h>
<stdarg.h>
<stdbool.h>
<stddef.h>
<stdint.h>
これらは言語の基本的な機能を提供し、関数を宣言しません ( の機能<stdarg.h>
は標準でマクロとして明示的に定義されています)。複素数を含まないことに注意してください。
Hosted - 実装により、標準で定義された完全なライブラリが提供されます。
独立した実装の要点は、一般に標準ライブラリ、特に標準 I/O 関数に邪魔されずに必要なコードを記述できるようにすることです。欠点は、これらの機能を提供できるだけでなく、提供しなければならないこと、または実装によって提供される代替手段を利用することです。独立した実装では、プログラムのエントリ ポイントを呼び出す必要がないことに注意してくださいmain
。
あなたが求めているのは、独立した実装、またはホストされた実装の独立した部分を使用することです。ヘッダーを使用しますが (正気でない限り)、独立した実装で使用するためにリストされているもの以外の標準 C ライブラリ ヘッダーにはならないでしょう。
最小限の C 環境に関する他の回答は適切ですが、ここでは別のより抽象的な角度を示します。
C 標準では、2 種類の「観察可能な副作用」が定義されています。これは基本的に、プログラムが実行することで、コンパイラによって最適化または変更できないことを意味します。volatile
これらは、最初に I/O 関数の呼び出しであり、次にオブジェクトの読み取りと書き込みです。
stdio
OS の存在に依存する C 実装の他の部分にアクセスできない場合は、I/O 関数を使用できません。volatile
つまり、プログラムが実際に「実行」するのは、オブジェクトへの読み取りと書き込みだけです。実際には、実際にすべてをマークする必要がある場合とない場合がありますvolatile
。これは、C 実装がおそらく標準を超えた保証を提供するためです。ビープ音を鳴らす CPU 命令がある場合、実際には関数ではなくても、コンパイラはそれ (および一般的なインライン アセンブリ) を I/O 関数のように扱います。
言い換えれば、ブートローダーが達成するはずのことを達成するために、低レベルのハードウェアアクセスを使用する必要があります (つまり、画面にメッセージを表示し、OS が実行するために必要なリソースをいくつか確立し、それをロードします)。そしてそれを実行します)。もちろん、このアクセスは完全に実装に依存します。ハードウェア ベンダーはライブラリを提供して支援する場合がありますが、それらは標準の C ヘッダーではありません。
stdio
標準入出力の略です。その名の通り、標準IOに関するものが入っています。stdio.hのウィキペディアの記事には、stdio.hの内容がリストされています。それらを使用する場合は、stdio.h が必要になります。詳細については、stdio.hのman ページも参照してください。
また、OS の部分について言えば、OS を作成することは、たとえそれがアカデミックなものであっても、単純なプログラミング以上のものです。そこに飛びつく前に、データ構造、アルゴリズム、OS 理論などを学ぶ必要があります。The Design of the UNIX Operating Systemは、OS を学ぶのにとても良い本です。Nachosはアカデミックな OS シミュレーション プログラムです。それも確認できます。また、OS の熱狂的なファンであれば、Linus Torvalds Just for Funの自伝を読む必要があります。まあ、技術書ではありませんが、OSを書くということの意味を感じていただけると思います。
設計が不十分でない限り、ブートローダーにはほぼ確実に #include ディレクティブがあります。あなたがその引用をどこで手に入れたのかわかりませんが、おそらくあなたはそれを誤解しています. ブートローダは、最初の低レベル プロセッサの初期化と C ランタイム環境の初期化のために、純粋なアセンブリ コードで常に開始されます。このコードを C で書くことはまったく不可能です。ただし、残りのコードは、環境 (メモリなど) の制限内で、必要に応じて複雑にすることができます。
stdio は、入力と出力を受け取ることができるある種のデバイスに接続された一連のファイル ストリームです。stdin、stdout、stderr、またはそれらのサブセットを実装できます。また、任意のファイル ストリームを開くことができるファイル システムを実装することもできます。最近の OS では、これは通常、ある種の端末に接続されます。これは、モニターに表示される仮想端末であり、グラフィックス ドライバーなどが必要になるため、その間にかなりのレイヤーが含まれます。初期の組み込みシステムでは、stdio がシリアル ポートまたは LED ディスプレイに接続されている場合があります。
stdio はread()
およびwrite()
関数で実装されます。printf()
これらが実装されていない場合、fprintf()
、 、 などの stdio 関数を使用できませfgets()
ん。これは、グラフィック ディスプレイ、シリアル ポートなどに書き込めないという意味ではありません。それを行うための標準的な機能がなく、カスタム関数を呼び出す必要があることを意味します。
あなたの質問に答えるには、stdio がなくても C で何でもできます。いずれにせよ、すべて C で書かれています。C 標準ライブラリに実装されている一般的な機能が失われているだけです。
taskinoor が言及しているように、ウィキペディアはstdio.hに含まれるものに関する優れたリファレンスを提供します。
stdio.h なしで可能なことについては、stdio.h で可能なことのほとんどすべてを行うことができますが、特定のことについてはより多くの作業を行う必要があります。たとえば、ファイルを使用する場合は、ファイルの独自の抽象化と、それを操作するための独自のインターフェイスを定義する必要があります。キーボードから入力を読み取りたい場合は、呼び出す代わりに、scanf()
アセンブリ コードを使用して BIOS 割り込みを呼び出す必要があります。
これが、OS のプログラミングの性質です。これらの高レベルの構成体は、構成体とそれを操作するための API を定義するまで存在しません。最小の基本機能から始めて、それらをグループ化し、ますます便利で複雑な構造を作成する必要があります。