小型組み込み機器向けLinux ──MMUを持たないマイクロプロセッサで動作するしくみ
●システム・コール
uClinuxのターゲット・プロセッサはMMUのをサポートしていないため,Linuxシステム・インターフェースにいくつかの変更が発生します.その中の最大のものは,forkがないことです.
通常,fork()は子プロセス(プロセスのクローン)を生成します.Linuxでは,fork()はcopy_on_writeページを用いて実行されます.MMUを持たないuClinuxの場合,プロセスを完全かつ確実に複製することができず,またcopy_on_writeへのアクセスもありません.
fork()の不在を補うため,uClinuxにはvfork()が実装されています.親プロセスが子プロセスを生成するためにvfork()を呼び込む際,両者がスタックまでを併せたメモリ・スペースを共有します.vfork()は,子プロセスがexit()もしくはexecve()を呼び込むコールを実行するまで,親プロセスの実行を停止します.そのほかの点ではマルチタスクに影響はありません.しかし,これは同時に,fork()を多用する旧式のネットワーク・デーモンを修正しなければならないことを意味します.また,子プロセスは親プロセスと同じアドレス空間内で実行されるため,両プロセスのビヘイビアの修正が必要となる場合があります.
最近のプログラムのほとんどは,基本タスクの実行を子プロセスとして処理し,大きな負荷がかかる場合でもシステムにインタラクティブな動きを維持させています.こうしたプログラムでは,同様のタスクをuClinuxで実行させる際に相当なリワークが必要になる場合があります.キーとなるアプリケーションがこのような構造に大きく依存する場合,アプリケーションの再構築か,もしくはMMUを持つプロセッサの導入が必要になります.
hypedと呼ばれる仮想のシンプル・ネットワーク・デーモンを用い,fork()の使用例を紹介します.hypedはつねに,ネットワーク・クライアントからの接続のため,well-knownネットワーク・ポート(もしくはソケット)をリスンしています.クライアントが接続するとhypedは新規の接続情報(新規ソケット番号)を与えてfork()を呼び出します.その後,子プロセスがクライアントの新規ソケットへの再接続を受け入れ,親プロセスは次の新たな接続に対応できるように解放します.
uClinuxは,自動生成スタックとbrk()を実装していないため,ユーザ空間で動作するプログラムがメモリを割り当てる際にはmmap()コマンドを使わなければなりません.利便性のため,Cライブラリではmmap()のラッパとしてmalloc()を実行しています.プログラムのスタック・サイズを設定するためには,コンパイル時のオプションがあります.