Linuxシステムコールの勉強(その1)

Linuxシステムコール

Linuxシステムコール

久しくCを書いてないのでひとまず思い出すところから始めます。↑の本を引っ張り出して勉強することにして、まずはこの本の内容を元に自分の解釈を加えながらまとめていきます。丸写しはよろしくないので、それはしないようにします。


まずシステムコールの定義ですが、OSの機能を利用するための関数群です。WindowsだとWin32APIなどがこれに該当するのですが、直接ハードウェアにアクセスするようなコードを書くのではなく、システムコールを介してアクセスする事でハードの差異はOSやらドライバやらで全部吸収してもらえるようになるというたいへんありがたい関数です。このありがたさを知っていればシステムコールに足を向けて寝るなんてとてもとても出来ません。


    1. システムコールとはOS機能を呼び出すための関数群(WindowsだとAPI)
    2. WindowsのGetLastError()はerrnoに対応
    3. perrorに上記errnoを渡せばエラーメッセージを取得可
    4. exec()はプロセスの置換(自らを他のプロセスに置き換える)
    5. プロセスの複製はfork()


さらにexec()とfork()について掘り下げてみます。




まずはexec()について。
exec()は自プロセスを他プロセスへ置換するためのシステムコールです。fork()と組み合わせる事で新しいプロセスを新規に作る事が出来ます。
# 詳しくは次回のfork()を参照

1. exec()にはl系execとv系execがある

 exec?()の?に入る文字がvのものをv系,lのものをl系と呼びます。特徴は以下のとおり。

分類 特性 補足
l系 コマンドと引数を一つ一つ記述しないといけない 引数が少ない時は記述が簡単便利だけど、逆に引数が複数あるときは不便
さらに最後の引数として末尾を表すNULLを渡す必要あり
v系 引数を配列にして記述しないといけない 引数が多い時は記述が簡易化だけど、引数が少ないときは不便


まあ不便とか言わずに使い分けろということで。
 

2. exec()には関数名の末尾にp,eが付くものがある

システムコール
(?にはl,vが入ります)
説明
exec?p 環境変数PATHが自動で引き渡されているので便利
exec?e 任意の環境変数を引き渡す事が出来るので便利

3. システムコールはexecve()のみ

 他のexec()たちはexecve()のラッパー関数*1だそうです。


exec()は自身を他のプロセスに変身させるシステムコールと覚えておくことにします。



fork()はプロセスの分身を作るためのシステムコールです。
これだけだとイメージが沸きにくいので実際に動かしてみます。

#include <unistd.h>
#include <stdio.h>

int main()
{
  int i ;

  printf("start!!\n");
  printf("my process id = %d\n",getpid()); // 現在のプロセスIDを取得 //

  printf("fork start\n");
  fork(); // 複製 //
  printf("fork end\n");

  for(i = 0 ; i < 4 ; i++)
  {
    printf("%02d: PID = %d running...\n", i , getpid());
    sleep(1); // 1msec wait //
  }
  return 0;

}


fork()したところから下はそれぞれ別のプロセス(一つは生成元のプロセスでもう一つは生成元からコピーされたプロセス)が実行してるのですがこれを見ると何となく気持ち悪い....。でもこれがLinuxのプロセス生成に必要な動作なんですね。

forループは4回のはずが、その前にfork()してあるので、それぞれ4回ずつの計8回の出力がされています。
fork()とexec()は結構大事だった(遠い)記憶があるので、もう少し試してみようと思うけど、とりあえず今日はここまで。字かいはfork()についてもう少し調べてみます。


次へ進む

*1:特定の関数に対して引数などを初期値として与えることで動作を限定した関数をこう呼びます