根本的な理解が足りていないのかもしれませんが、質問させてください。
C言語でHelloWorldプログラムを作ったとします。
その中で、以下のコードがあります。
printf("Hello World");
この部分を実行すると、標準Cライブラリがwrite()システムコールを発行して
カーネルに実行が移り、ディスプレイに「Hello World」が表示されます。
この説明は理解できますが、そのカーネルの処理がC言語で書かれているというのが理解できません。
write()システムコールに対応するカーネル処理のソースコードはC言語で
printf("~");
と書かれているのでしょうか?
メモリを直接操作するようなコードをアセンブリで書くのではないでしょうか?
気になる質問をクリップする
クリップした質問は、後からいつでもMYページで確認できます。
またクリップした質問に回答があった際、通知やメールを受け取ることができます。
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。
回答7件
0
ベストアンサー
まず、Cにはホスト環境とフリースタンディング環境という二つの環境があることをご存じですか?
よく見る通常のCのプログラム、printf
関数などを使ったプログラムはホスト環境と言われるもので、OS上で動作すること前提としています。各標準Cライブラリの各関数の動作はOSが環境を用意しているからこそ、動作できると言うことです。
対して、フリーホスティング環境はOSを前提としないプログラムです。OSが提供するような機能が使えないため、標準Cライブラリも限られた物しか使えません。printf
関数はもちろん、プログラムを終了するためのexit
関数すら使えないようになっています。その代わり、main
関数がエントリーリポイントになるという制約から外れ、その環境に応じたエントリーポイントから始まることになります。
カーネルはOSの役目を担うのですので、もちろん、OS上で動作する物ではありません。ということで、カーネルはCでできていると言っても、通常見るようなホスト環境ではなく、フリースタンディング環境のCで書かれています。つまり、カーネルが書かれているフリーホスティング環境には、そもそもprintf
関数が存在しないのであり、write
を実装しようにも、他の方法を使わなければなりません。アセンブリでシステムコール呼び出しを実装し、それらのシステムコールを駆使する形で作られることになります。
そもそも、カーネルはCだけでできているのではありません。1.5%はアセンブリでできています。しかし、アセンブリで全て書くことは全く現実的ではないため、Cでは直接記述できないCPUへの特権命令等をアセンブリで書いて、それらをシステムコール等としてまとめて、Cであればどこからでも使える関数(またはマクロ関数)にしています。そして、ただの計算処理だけを行うような部分、つまりは、別途作成したシステムコール等があれば実現できるような部分をCで書いていると言うことです。そして、そういった部分が大部分を占めるため、ほとんどがCでできているように見えると言うだけです。
参考:
投稿2018/03/28 11:34
総合スコア21737
0
Linuxだったらカーネルのソースコードを実際に読んでみてはいかがでしょうか。
ネットで検索すれば、親切な方がわざわざどのあたりがどのファイルかなど解説してくれているサイトなどもあります。
そこで納得いかなければ再度質問されてはいかがでしょうか。
投稿2018/03/28 11:39
総合スコア3041
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。
0
「カーネルがC言語で書かれている」といっても、当然ながら標準ライブラリは使えません(逆に、標準ライブラリがカーネルを使って実装されています)。実際の出力部分は、アセンブラあるいはCのメモリ操作で書かれていることと思います。
カーネルの大半がC言語で書かれている理由としては移植性があります。CPUやハードウェアに依存する一部のコードだけアセンブラで書くようにして、残りのコードはコンパイルさえすれば環境を超えて使えるようになっています。
投稿2018/03/28 09:39
総合スコア145932
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。
2018/03/28 09:56
2018/03/28 10:08
2018/03/28 10:13
2018/03/31 00:20
0
write()システムコールに対応するカーネル処理のソースコードはC言語で
Linux/Unix だと多分、そうでしょう。
他のOSではどうかは知りませんが、昔、使った事のあるOSでは違いました。(C言語は後から、サポートされていた) C言語である必要は無いが、C言語が主流になっただけです。
実際のコードについては、
printf("~");
という事はありえません。別の方が書かれているように、カーネル、、、と言うより、標準ライブラリのソースを読めば、分かると思いますが、printf()は、内部的に、write()を呼び出しているのでは思います。(最近の見てないので本当のところは知りませんが) また、大昔の様に直接、端末に出力するような時代ならともかく、今時は、出力用のデバイスドライバ呼出ししかないと思いますので、標準化された(デバイスドライバ)呼出しを行っていると思います。
あと、カーネルでの処理ですが、時代によってカーネルの範囲(定義)は異なりますが、今はどの辺でしょうか? Linux/Unix は比較的狭い範囲と理解していますが、標準ライブラリと 外部I/Oのやり取りくらいは含むかな、、と思います。
余談ですが、C言語は昔、高級アセンブラと呼ばれていました。その位、アセンブラに近いという事で、アセンブラに近い効率を簡潔な表記で記述できます。
投稿2018/03/28 12:07
総合スコア6385
0
おおよそ認識はあっているかと思います。
ユーザー空間でprintfを呼び出すと標準ライブラリでstdout(ファイルディスクリプタ1)に対してwriteシステムコールを発行します。ファイルディスクリプタを使って対応するデバイスドライバが選ばれ呼び出されます。writeシステムコールの中身はデバイスドライバに実装されています。
デバイスドライバがどのように実装されるかはハードウェアによって異なるので一概には言えません。またデバイスドライバは何層にも重なっているので一番始めは抽象化されたttyデバイスになりますが、最終的にはメモリ操作かIO操作になります。(C言語的にポインタを使うか、IOのための専用命令を出すためにアセンブラで記述する)
投稿2018/03/28 22:13
総合スコア910
0
こんにちは。
C言語は大きく2つの部分に分かれています。C言語コア部と標準ライブラリ部です。
標準ライブラリはあくまでもライブラリの一種です。例えばOpenCVなどもライブラリの一種ですね。
OSのカーネルを書く際にOpenCVを使う人はまずいないと思います。同様に標準ライブラリも使われない(使えない)関数がほとんどです。そして、printf()は標準ライブラリに含まれている関数です。
C言語コア部はCコンパイラが解釈するプログラミング言語の文法を規定します。
アセンブラはアセンブリ言語で書かれたソース・プログラムをマシン語へ変換します。
CコンパイラはC言語で書かれたソース・プログラムをマシン語へ変換します。
従って、このコンパイラとしての機能を使ってカーネルを書くことになんら問題はありません。
投稿2018/03/28 12:37
総合スコア23272
あなたの回答
tips
太字
斜体
打ち消し線
見出し
引用テキストの挿入
コードの挿入
リンクの挿入
リストの挿入
番号リストの挿入
表の挿入
水平線の挿入
プレビュー
質問の解決につながる回答をしましょう。 サンプルコードなど、より具体的な説明があると質問者の理解の助けになります。 また、読む側のことを考えた、分かりやすい文章を心がけましょう。
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。
2018/03/29 02:39