Linuxシステムコール:Linuxのメモリ空間

Linuxのメモリ空間

 システムコールについて説明する前に、Linuxのメモリ空間について解説します。Linux上で動作するプログラムは、カーネル区間とユーザー空間に分けられています。


 カーネル空間はその名が示すように、Linuxカーネルそのものが動作する空間で、物理アドレスを参照することができるため、すべてのハードウェア資源に直接アクセスすることができます。

 これに対してユーザー空間は、論理アドレスに変換されたメモリ空間で動作するためユーザー領域として割り当てられた空間内でしか動作することができません。この、限られたメモリ空間はプロセスが起動する毎にカーネルが割り当てを行います。

 なぜ、このような方式となっているのでしょうか?

 下記のプログラムをLinux上で実行するとどうなるか想像がつきますね?お手元のLinuxでソースをコンパイルして実行してみてください。

#include

#define MAX 4096 

static char buf[16]; 

int main(int argc, char** argv) { 

    int i; 

    for(i = 0; i < MAX; i++) { 
        buf[i] = ' '; 
    } 
}


実行すると、
「Segmentation fault (コアダンプ)」
と、表示されてプログラムは強制終了されてしまいます。

どうして強制終了されたのでしょうか?

 このプログラムは、ユーザー空間で実行しました。カーネルはプロセスを起動する時に論理アドレスによる限られたメモリ空間を割り当てます。さきほどのプログラムは自分のメモリの外側までアクセスしたので、不正なメモリアクセスを行ったとして強制終了されました。

 このようなシステム構成とすることで、ある1つのプログラムが問題を起こしても他のプログラムやハードウェアには問題を与えにくくすることができます。こうすることで、システム全体が暴走したり、突然停止するような事態を防ぐことができます。

 この、カーネル空間とユーザー空間は、CPUのハード的な能力を使って実現しています。CPUは幾つかのモードを持っており、リングプロテクションと呼ばれる概念で示される機能で実現しています。


 リングプロテクションの概念は内側がより権限を持つレベルを示しており、LinuxではRing0のカーネルとRing3のアプリケーションを使っています。カーネル空間は、Ring0で動作します。ユーザー空間のプログラムはRing3で動作しています。

 先程の「Segmentation fault (コアダンプ)」を発生させたプログラムはアプリケーション(Ring3)であるため、認められないアドレスへのアクセスが検出されたため、強制終了されましたが、同様のことをカーネル空間=Ring0で行った場合、他のプログラム領域あるいはハードウェアに不正なアクセスを行って暴走、あるいはシステム停止が発生する可能性があります。しかし、基本的にカーネル空間にはOSの機能以外のプログラムを配置することはありませんので、不用意なプログラムが意図せず紛れ込むことはありません。

 しかしその反面、ユーザープログラムは論理アドレス空間で動作するため、ハードウェアの物理的なアドレスにユーザー空間のプログラムはアクセスすることはできなくなってしまいます。

 このように、ユーザー空間では直接ハードウェアにアクセスすることができないため、ハードウェアアクセスなど共通の機能をOSに集約し、それをアプリケーションから利用できるようにするためのインターフェイスがシステムコールとして整備されています。

 また、アプリケーション側から物理的なハードウェアを隠蔽することでハードウェアの抽象化を行ったり、ディレクトリ構造と言った論理的な構造をアプリケーションに与えることも可能となります。

 ユーザー空間で動作するプログラムについても、プロセスごとに別々の論理アドレスになっているので他のプロセスと直接データのやり取りはできません。しかし、それではシステム全体を協調動作することができないため、プロセス間通信(IPC : Inter Process Communication)などのサービスがOSの機能として組み込まれています。

 これらのOSが提供する機能を利用するインターフェイスもシステムコールとして実装されています。


Lightning Brains

コメント

このブログの人気の投稿

Linuxシステムコール、共有メモリの使い方

Linuxシステムコール、メッセージキューの使い方

Linuxシステムコール、セマフォの使い方