差分

移動先: 案内検索

カーネルの構造と機能

1,178 バイト除去, 2020年9月20日 (日) 16:30
/* カーネルを機能から見てみる */  言葉のゆらぎを修正
=== カーネル空間とユーザ空間 ===
[[オペレーティングシステムとは何か#何をさしてオペレーティングシステムと呼ぶのか|何をさしてオペレーティングシステムと呼ぶのか]]の議論でもでも少し取り上げましたが、の議論でも少し取り上げましたが、
いろいろな切口でカーネルを眺めることはできます。ここでは、最初はわかりやすいであろう「プログラムが動作する」という切口から考えてみます。
 
[[File:User-kernel-mode.png|thumb|right|300px|ユーザ空間とカーネル空間]]
プログラムが動作する時、システム上では2つの処理空間で処理が行われます。1つはユーザ空間(User space)、もう1つがカーネル空間(Kernel space)です。この2つの空間を行き来して処理を進めます。といっても、プログラムが動作する際、どちらの空間で処理されているかといったことをユーザが意識する必要はありません。
 
--------------------------
ユーザ空間
----[システムコール]------
カーネル空間
--------------------------
ユーザ空間は、ユーザに割り当てられる計算リソースで、実行しているプログラムが直接アクセス可能なリソースです。
一方、カーネル空間はユーザが直接アクセスできない空間です。システムコール(UNIXのカーネルAPI) を呼ぶことや、
あるいは/sys/以下のファイルのようにファイルの形でカーネルへのインタフェースを介してカーネルの機能を利用できる形にしています。ユーザからは直接カーネル空間を操作することはできません。Kernel(核)という言葉は元々は堅い殻に守られた種の意味ですが、この意味のようにユーザ側から見ると、カーネル空間は堅い殻に守られたオペレーティングシステム内部というように見えます。以下のファイルのようにファイルの形でカーネルへのインタフェースを介してカーネルの機能を利用できる形にしています。ユーザからは直接カーネル空間を操作することはできません。Kernel(核)という言葉は元々は堅い殻に守られた[https://en.wikipedia.org/wiki/Drupe ''種の意味'']ですが、この意味のようにユーザ側から見ると、カーネル空間は堅い殻に守られたオペレーティングシステム内部というように見えます。
[[File:User-kernel-mode-2.png|thumb|left|300px|write(2)実行時のタイムライン]]
ここでプログラムがデータを処理し、ファイルにデータを書き込む時を考えてみましょう。ユーザ空間でデータが処理され、write(2)でファイルに書込にいきます。すると、制御は一旦カーネル空間に移ります。カーネルでの処理が済んで、またユーザ空間に戻ってきます。このようにカーネルはユーザ空間で動くプログラムの制御と、カーネル内での必要な資源の提供と管理を行っています。以下に単純化したモデルを示してみます。
 
;補足: write(2)と書いている2の意味はオンラインマニュアルの区分を示しています。2はシステムコール、3はライブラリの意味です。 manコマンドにオプション 2 write と与えるとwrite(2)が表示されます。
write(fd,buf,length)
.
------------------->時間軸
.
------------------------------
ユーザ空間
----+ +------>処理の流れ
| |
-----|--------|----------------
| |
+-+ +-+ カーネル空間
-------|---|------------------
+--+
ハードウェア資源
==== システムコール ====
システムコールはユーザ空間からカーネル空間で処理を行うための切替えポイントです。今風にいうならばカーネルとのAPIとして用意された関数群です。UNIXではシステムコールと呼びます。
システムコールはたくさんあります。どのようなシステムコールがあるのかを調べるにはオンラインマニュアルをチェックするのがいいでしょう。システムコールはセクション2システムコール<ref>システムコールの実装をチェックするのに便利なサイト https://filippo.io/linux-syscall-table/</ref>はたくさんあります。どのようなシステムコールがあるのかを調べるにはオンラインマニュアルをチェックするのがいいでしょう。システムコールはセクション2
<ref>
/usr/share/man/man2
;調べてみよう: 今使っているLinuxにはおおよそいくつのシステムコールが用意されているのが調べてみよう。次に、既に使われなくなりなくなったシステムコールと、互換性のために残してあるが使用するのに推奨されていないシステムコールを1つ以上みつけてみよう。欠番となっているシステムコールを探すには [http://uc2.h2np.net/misc/codes/unistd/ /usr/include/asm/unistd.hがヒントになります。h] がヒントになります。
fwrite(3)の方は、ユーザ空間で動作していて、さらに入出力を効率的にするためのバッファを用いています。バッファはファイルポインタFILE *stream が保持しています。/usr/include/libio.hの構造体である [http://uc2.h2np.net/misc/codes/libio.h.html#N245 struct _IO_FILE ] を見てみるとわかります。ですからfwrite(3)を呼び出したからといって、その先のファイル(あるいは書き出す実体)へ書き込んでいるとは限りません。
カーネルの構造を考えるために、カーネルが提供している主要な機能を書き出してみます。この分類はカーネルのソースコードレベルで分類しているのを参考にしています。個々のソースコードファイルは機能別に分割されており、さらにディレクトリは大きなレベルでの機能の違いで分類されています。これを分類の指針とするとかなり判りやすくなります。
 
[[File:Layer-of-System.png|thumb|right|400px|System Layer]]
個々の説明は後の章に譲るとして、ここでは概観と個々の機能の簡単な説明をします。
* プロセス管理
** プロセス生成・消滅
** スケジュラスケジューラ
+---------------------------------------------------------------+ | アプリケーション | +---------------------------------------------------------------+ | システムコール ・ ファイル(デバイスファイルなど) | +------------+----- --+----------------+--------------+---------+ |プロセス管理 |記憶管理|ファイルシステム |プロセス間通信 |ネットワーク | | | +----+----------------+--------------+----------+ | | | デバイスドライバ | | | | ( 仮想デバイス ・ 各種 I/Oドライバ ) | +---------------------------------------------------------------+ | 各種ハードウェア | +---------------------------------------------------------------+
==== プロセス管理 ====
プロセス管理は、プロセスの生成と消滅についての処理と、そのプロセスのスケジュールを管理するスケジュラーの部分です。利用しているCPU数と比べプロセス数の方がはるかに多いわけですから、プロセスに上手に計算資源を割り振ってあげなければなりません。[http://uc2.h2np.net/index.php/%E3%83%97%E3%83%AD%E3%82%BB%E3%82%B9%E7%AE%A1%E7%90%86 プロセス]とはオペレーティングシステム上で動いている実行実体です。ユーザーは意識することなくプログラムが動いている、程度の認識しか持ちませんが、プロセスは実行を行うための計算資源を管理しています。[[プロセス管理]]とは、プロセスの生成と消滅についての処理と、そのプロセスのスケジュールを管理するスケジューラの部分です。利用しているCPU数と比べプロセス数の方がはるかに多いわけですから、プロセスに上手に計算資源を割り振ってあげなければなりません。   
ここではプロセスという言葉をつかっていますが、タスクやスレッドという言葉もあります。ある処理の計算資源と処理の流れをすべて含めて呼ぶ時はタスクです。計算資源は共有していてる複数あるいは単数の処理の流れのことをスレッドと呼びます。ですから1つのタスクで複数のスレッドを持つことができます。1つのタスクに対し、1つのスレッドだけの場合、これをUNIXの伝統的な呼び方であるプロセスと呼びます。1タスク・1スレッドが伝統的な意味でのUNIXのプロセスと同等の意味を持ちます。;補足: CPU(演算装置)資源は、プログラムが実行するのに必要な計算資源の中の1つにしか過ぎません。また1つの計算資源の中に複数のCPU資源を持つことが可能です。
UNIXは最初からスレッドを持っていたわけではありません。80年代に入ってから色々な組織がスレッドの実装を試みました。Brown Univ.のブラウンスレッド、サンマイクロシステムズのLWP (Lightweiht Process)、DECのCMA スレッド、CMUのCスレッドパッケージがあります。各々互換性はありません。紆余曲折あり、現在ではPOSIX仕様のスレッドであるpthreads(7)が主流になっています。
===== スケジューリングの種類 =====
プロセスのスケジュリングでは、Linuxの場合、 プロセスのスケジューリングでは、Linuxの場合、 システムコールsched_setscheduler(2)を使い、プロセスのスケジュリングの方法を指定することができます。を使い、プロセスのスケジューリングの方法を指定することができます。
* SCHED_FIFO: First-In-First-Out
* SCHED_OTHER: デフォルトのLinuxのタイムシェア
* SCHED_BATCH: バッチでの処理を行う(2.6.12以降)
* SCHED_IDLE: 非常に低いプライオリティ
FIFOは、そのプロセスがCPU資源を占有する方式です。CPU資源を占有といっても、一般ユーザで動作するよりもさらに、優先度よりも高い優先度で動くプロセスあると、そちらの方を優先します。ラウンドロビンは順繰りにプロセスが処理されます。デフォルトでは、プロセスの動作時間を見て、優先順位を計算し、その優先順位が高い方から処理するようになっています。このスケジュリングの処理アルゴリズムはLinux FIFOは、そのプロセスがCPU資源を占有する方式です。CPU資源を占有といっても、一般ユーザで動作するよりもさらに、優先度よりも高い優先度で動くプロセスあると、そちらの方を優先します。ラウンドロビンは順繰りにプロセスが処理されます。デフォルトでは、プロセスの動作時間を見て、優先順位を計算し、その優先順位が高い方から処理するようになっています。このスケジューリングの処理アルゴリズムはLinux 2.6 では入れ換えれており処理効率がよくなっています。
2.6.12ではあたらしくSCHED_BATCHのスケジュールが加わり、
2.6.23ではCFS( Completely Fair Scheduler )スケジューラ
</ref>
が使えるようになりました。
オペレーティングシステムの心臓部ともいえるスケジュラー部分でも進化は続いています。  ;補足: Linux 2.4あたりまでのLinuxのプロセススケジュラーはやはり他のオペレーティングシステムからみると見劣りするものだというのは否定できない事実です。オペレーティングシステムの心臓部ともいえるスケジューラ部分でも進化は続いています。
==== ファイルシステム ====
UNIXのファイルの特徴はファイルがバイト単位のデータストリームであることです。[[ファイルシステム]]を説明する前に、まずはUNIXのファイルという考え方について説明します。UNIXのファイルの特徴はファイルがバイト単位のデータストリームです。
ファイルの中身というのは最初から最後に向かって1バイトづつのデータの列であるだけでそれ以上でもそれ以下でもありません。
カーネルでは、そこまでしか関知しません。データの扱いに関してはプログラム側が決めます。
;調べてみよう: 大型汎用機<ref>http://www.hitachi.co.jp/Prod/comp/soft1/VOS3FSVOS3/v3ga0226index.htmhtml</ref>ではどのようにファイルを扱うのか調べてみよう。
[http://e2fsprogs.sourceforge.net/ext2.html ext2]、
[http://e2fsprogs.sourceforge.net/ext2.html ext3]、
[https://ext4.wiki.kernel.org/index.php/Main_Page ext4]、
[http://oss.sgi.com/projects/xfs/ XFS]、
[http://jfs.sourceforge.net/ JFS]、
[http://oss.oracle.com/projects/ocfs2/ OCFS2]
などいろいろな種類のファイルシステム<ref>ReiserFSは、まだカーネルに入っているが、あえて抜いた。ReiserFSは、まだカーネルに入っていますが今後のメンテナンスがみこめないためリストに載せていません。</ref>が用意されています。ファイルシステムの部分でも、このようにレイヤ化されています。また名前付きパイプが用意されています<ref>https://help.ubuntu.com/community/LinuxFilesystemsExplained</ref>。ファイルシステムの部分でも、このようにレイヤ化されています。また名前付きパイプ(FIFO)はプログラム間でデータを"流す"ために使われる見かけ上のファイルです。あるいは/procなどのファイルは、実際にはファイルではなくファイルのように見せかけたカーネルとのAPIになっています。
唯一の共通点は、ファイルシステム上の名前空間に存在し、統一的なファイルへのアクセスが提供されているということです。そのためプログラム側はファイルを介すという形でのデータの入出力のためのアクセス方法がシンプルにな:ります。唯一の共通点は、ファイルシステム上の名前空間に存在し、統一的なファイルへのアクセスが提供されているということです。そのためプログラム側はファイルを介すという形でのデータの入出力のためのアクセス方法がシンプルになります。
;補足: /p/tcp/www.sample.com/wwwというファイルをアクセスするとwww.sample.com の www ポートがアクセスできるというファイルシステム [http://www.usenix.org/publications/library/proceedings/neworl/stevens.html Portalsを4.4BSDに対して実装]した人もいます。
==== プロセス間通信 ====
セマフォ ここでの[[プロセス間通信]]の意味は同一カーネル上に存在しているプログラム間での通信です。ここではTCP/IPなどの通信はネットワーク通信と分類しています。  さてプロセス間通信で特徴的なものとして最初にあげるのはセマフォ (semaphore)は別々に動作するプロセス間での同期を取るためのメカニズムで、です。セマフォは別々に動作するプロセス間での同期を取るためのメカニズムで、
セマフォを介してプロセス間で正しい処理順番を確保するような仕組が出来るようになっています。
どのプロセスからもアクセスでき、そして情報の書き込み、取り出しに関しては順序を守ってくれます。
</ref>
==== 記憶管理 ====
記憶管理はプロセスが使っているメモリ空間の割り当ての管理です。[[記憶管理]]はプロセスが使っているメモリ空間の割り当ての管理です。
メモリ空間といってもプロセス自体はハードウェアのメモリを直接意識していません。
カーネル側がプロセスに割り当てた仮想的に扱う記憶空間を管理しているため、
シェアードメモリはプロセス間で同じ記憶空間を共有するメカニズムです。
==== ネットワーク ====
現代において、ネットワークの機能はオペレーティングシステムの中でも重要な役割を果たすようになっています。
;調べてみよう: 使っているカーネルのバージョンでは、どんなプロトコルをサポートしているだろうか。
 ==== デバイスドライバ ====
----
[[目次]]へ
 
このページへのショートURL: http://uc2.h2np.net/i/1a.html