FAQ

uclinuxとlinuxの違いを教えてください

uClinuxは、MMUを持たないCPUをサポートしているLinuxカーネルです。uClinuxはMMUを持たないことで

  • ページングによるメモリ保護が無い
    • アプリケーションから他のプロセスやカーネルのメモリ空間を壊すことができる
  • fork()が使えない
    • 代りにvforkを使う
  • 共有ライブラリが使えない
  • スワップが使えない
  • プログラムを全てメモリにコピーする必要がある
    • busyboxのように一部しか使わないプログラムでも、全部ロード

など、制限があります。

(SUSv2 / POSIX ドラフトより引用) vfork() 関数は fork(2) と同じ働きをするが、 vfork() で作成されたプロセスが vfork() からの返り値を格納している pid_t 型の変数以外を変更したり、 vfork() を呼び出している関数から return したり、 _exit(2) や exec(3) 族の関数をコールする前に他の関数をコールした場合の動作が未定義であるという点が異なる。 と記載されています。 例えば
 1 #include <unistd.h>
 2 #include <stdlib.h>
 3 #include <stdio.h>
 4
 5 int main()
 6 {
 7         int a = 0;
 8         pid_t ret;
 9
10         ret = vfork();
11         if (ret == 0) {
12         /* chlid */
13                 a = 1;
14                 _exit(1);
15         }
16         else if (ret < 0)
17         /* error */
18                 exit(-1);
19
20         /* parent */
21         printf("a = %d\n", a);
22         return 0;
23 }
というコードがあったとしましょう。Linuxであれば、子プロセスと親プロセスのプロセス空間は別ですので、13行目の
13                 a = 1;
は、親プロセスには影響がありません。しかしvfork()の場合は、動作保証されていません。 vfork()を使って子プロセスを生成するときは、vfork()の直後にexec()を実行するようにしてください。 ### 親プロセスはスケジュールされず停止する vfork()では子プロセスが - _exit() - exec() を呼ぶまで親プロセスの実行が停止されます。つまり、子プロセスでblockしてしまうとdeadlockする可能性があります。 fork()を使った例で良く見るのが、pipeによる親との通信です。vfork()の場合これが問題になります。pipeにデータが無い状態で vfork()し、子プロセスがpipeからデータを読みだそうとしてblockします。forkであればこの時点で親プロセスがスケジュールされ pipeにデータを書き出すことができますが、vforkで生成された場合は親プロセスがスケジュールされないため、deadlockになります。 -->