->back to toppage

課題内容-level.2-

open system callを処理する部分を見つけよ。Linuxのシステムコールは、
  1. アプリケーションが呼び出すライブラリ
  2. ライブラリが呼び出すtrap
  3. trapを受け取り振り分ける部分
  4. 実際にkernel内部で処理する部分
がある。それぞれ、どこにあるのか調べよ。


報告内容

アプリケーションが呼び出すライブラリ

作成したアプリケーションがライブラリと結合されるのは リンカ(ld)が実行され、実行ファイルが生成されるときである。

ライブラリ自体はldがライブラリ参照に使うファイル(/usr/lib/libc.so)から /lib/libc.so.6 と /usr/lib/libc_nonshared.a であることがわかる。 コメントで書かれているように、 ほとんどのプログラムで使用されるshared libraryは前者のlibc.so.6、 いくつかの機能で使用されるstatic libraryは後者のlibc_nonshared.aである。
/usr/lib/libc_nonshared.a
/* GNU ld script
  Use the shared librarys but some functions are only in
  the staticc library. so try that secondarily.            */
OUTPUT_FORMAT(elf32-i386)
GROUP(/lib/libc.so.6 /usr/lib/libc_nonshared.a )


ライブラリに含まれる関数の中には、それ自体がさらにシステムコールを呼び出しているものがある。 これには、次のような利点がある。
  1. より使いやすい形で関数を利用できる。

    システムコールは非常に一般化された形で書いてあるので、 様々な要求に対応できるかわりに利用が難しい。 ライブラリ関数ではそれを使いやすいものにするために、 用途を限定したいくつかの関数を作ってその中からシステムコールを呼び出している。

  2. 移植性が高まる

    ライブラリは複数のアーキテクチャやカーネルなどでも同一の関数を提供するので、 システムコールの実装が違う別カーネルや、 アーキテクチャが全く違う別ハード上でもソースを変更することなく、 または最小限のソース変更で移植できる。



ライブラリが呼び出すtrap

ライブラリ内でシステムコールを呼び出すには、 レジスタに必要な引数をストアしてアセンブラのsc命令を実行する。 (powerpcの場合。i386はint 0x80命令) sc命令は、呼び出されたプログラムの直後のアドレスを格納し、 0xc00番地(powerpcの場合。i386は0x80番地)に格納されたシステムコールの割り込みベクタに処理を移す。


trap_init

linux/arch/(アーキテクチャ名)/kernel/trap.c に記述されている、 trapの初期化(割り込みベクタのレジスタ配置)を行う部分。
ppcでは、割り込みベクタ自体が0xc00番地に格納されるよう、 head.Sに直に記述してある(ppcはそのような記述が可能)ので、 trap_initは空のダミー関数になっている。


trapを受け取り振り分ける部分

0xc00番地の割り込みベクタでは、レジスタをカーネルスタックに退避し、 transfer_to_handlerを呼ぶ。
transfet_to_handlerからDoSyscallに処理が移る。DoSyscallはシステムコール 番号からテーブルを参照し、実際のシステムコールを呼び出す。
テーブルはソースファイル中では linux/arch/(アーキテクチャ名)/kernel/misc.S の中にある・・・と様々な場所に書いてあったが、 どうやらテーブルのみ別に分離されたらしく、 systbl.Sというファイル(powerpcの場合。i386ではsyscall_table.S) に別にとられていた。 それぞれのカーネルのソースは、以下の位置にある。

0xc00割り込みベクタ

powerpcの場合
linux/arch/powerpc/kernel/head_32.S
. . .
	
/* System call */
	. = 0xc00
SystemCall:
	EXCEPTION_PROLOG
	EXC_XFER_EE_LITE(0xc00, DoSyscall)

/* Single step - not used on 601 */
	EXCEPTION(0xd00, SingleStep, single_step_exception, EXC_XFER_STD)
	EXCEPTION(0xe00, Trap_0e, unknown_exception, EXC_XFER_EE)
	
. . .

他アーキテクチャでは基本的に linux/arch/(アーキテクチャ名)/kernel/head.S というファイルに記述されている。

DoSyscall

linux/arch/powrpc/kernel/entry_32.S

長くなるのでリンク--> entry_32.Sの一部


他アーキテクチャでは基本的に linux/arch/(アーキテクチャ名)/kernel/entry.S というファイルに記述されている。


実際にkernel内部で処理する部分

それぞれの関数の実体は、基本的にC言語で書かれており、 linux/fs/ 以下や linux/kernel 以下などkernelソース内に散在している。



考察

システムコールを呼び出すまでに必要なソース群は数回ジャンプしており、 結局いくつかのソースファイルを見て回ることになった。

機械語レベルに関わる箇所が多いためにアセンブラを使用している箇所が多かったが、 極端に複雑な記述はなかったように思える。

今回調査しきれなかったのは途中で出てきたtransfer_to_handler。 DoSyscallを呼び出すことまではわかったが、これ自身が何をしているものなのかは 突き止めることができなかった。powerpcに関するソース中でしか出てこないので、 アーキテクチャ固有の、必要なモノだとは思われる。 linux/-2.6.16.18/Documentation/powepc/cpu_features.txt 内には、それらしき記述があるが、カーネルソースにはそれらしき記述が見つからなかった。
... After detecting the processor type, the kernel patches out sections of code that shouldn't be used by writing nop's over it. Using cpufeatures requires just 2 macros (found in include/asm-ppc/cputable.h), as seen in head.S transfer_to_handler: #ifdef CONFIG_ALTIVEC BEGIN_FTR_SECTION mfspr r22,SPRN_VRSAVE /* if G4, save vrsave register value */ stw r22,THREAD_VRSAVE(r23) END_FTR_SECTION_IFSET(CPU_FTR_ALTIVEC) #endif /* CONFIG_ALTIVEC */ If CPU 0 supports Altivec, the code is left untouched. If it doesn't, both instructions are replaced with nop's. ...
cpu_features.txtの記述によれば、PowerPC G4 に搭載された ベクトル演算ユニットAltiVecを使用する場合にのみ有効になるマクロ (それ以外の場合は含まれる全命令がnopになる)らしいが、 今回との関わりが見つけられなかった。



参考文献



<-previous problem    go to top    next problem->