システムコール
システムコールとは
こんなことは誰でも知っていると思いますが念のため。
システムコール(英: system call、日: システム呼出し)とは、オペレーティングシステム (OS)より明確に言えばOSのカーネルの機能を呼び出すために使用される機構のこと。
ハードウェアをユーザーのアプリケーションが直接いじくりまわすと勝手にシステムや他のユーザーのファイルを破壊したりする可能性があり安全性が保障できないので、ユーザーはシステムコールを通じてカーネルへ命令をします。
ユーザーとカーネルを媒介する役割を果たすのがシステムコールというわけですね。
ただ例えばopen()システムコールを呼び出したときに一体どんな過程でファイルをオープンしているのかって詳細まで知っている人って少ないと思うんです。
ライブラリとシステムコールの違いも普通にプログラムを書く上で意識することもありません。
ライブラリ
カーネルの提供するシステムコールはとてもシンプルな実装になっています。
普通コンピューターアーキテクチャによってシステムコールの呼び出し方が異なりますが、カーネルの提供するシステムコールにその差を吸収する仕組みはありません。
システムコールの代わりにlibcのようなライブラリ機能がアーキテクチャの違いを吸収してくれています。
ユーザーがシステムコールを呼び出すとライブラリがそのコンピューターアーキテクチャにあった方法でシステムコール実行してくれます。
システムコールハンドラ
カーネルはシステムコールを番号で認識しています。
なのでユーザーがシステムコールを呼び出すときには必ずそのシステムコール番号をカーネルに通知しなければなりません。
カーネル内部にはシステムコールを割り当てるための配列が定義されており、その配列のインデックスがシステムコール番号になります。
システムコールハンドラ(関数の配列)から指定された番号(インデックス)に割り当てられたシステムコールサービスルーチンを呼び出します。
このハンドラはアセンブリ言語で記述されています。
システムコールサービスルーチン
システムコール番号からsys_…で定義されているシステムコールサービスルーチンを呼び出します。
ここで初めて要求された処理が実行され、処理が終わった後は規定の処理に基づきシステムコールルーチンを抜け、ユーザープロセスへ処理が移ります。
システムコールの呼び出し
具体的にユーザープロセスがシステムコールを呼び出す方法を見ていきます。
Linuxには二つの方法が用意されています。
int 0x80
コンピューターは高速で処理を切り替えながら同時に多くの処理を実行しています。
ある処理を実行している途中で別の処理を実行させることを割り込みと言います。
一口に割り込み処理といっても割り込みの種類に合わせて色んなものがあります。
発生した割り込みの種類に応じて割り込みベクタテーブルに登録された処理へ分岐させなければなりません。
その仕事を行うのが割り込みハンドラがです。
int n命令はnで指定された割り込み処理を実行させる命令です。
int 0x80はシステムコールの呼び出しになります。
eaxレジスタに呼び出すシステムコール(ファイルの読み出し、保存など)の番号、そのほかのレジスタに呼び出すシステムコールが必要とする引数(ファイルを読み出すメモリアドレスなど)を設定して実行します。
この命令が呼び出されるとコンピューターは実行中の処理を中断しベクタテーブルへジャンプ、eaxに設定されたエントリのシステムコールを実行します。
システムコール実行後はiret命令でユーザープロセスへ復帰します。

sysenter
作成中。
何故2種類のシステムコールの呼び出し方法がるかというとint 0x80は古いバージョンのLinuxはこれでしかシステムコールの呼び出しできませんでした。
リアルモードと全く同じような理由で過去の資源を活用する為に未だに残されている互換性の為の方法です。
コメント