Chapter1「Hello, world!」プログラム実行のからくりを解く

標準 Cライブラリを使わないプログラミング

 この章では,Cの教科書では定番の「Hello, world!」(hello.c)を題材に取り上げ,Cプログラムがどのようにコンパイルされ実行されるかを詳しく解説する.組み込みシステムの細部を把握するためには,まず最初に,実行可能ファイルが起動する技術背景を把握しておく必要があるからである.そして標準Cライブラリを使わずに直接システムコールを行い「Hello, world!」プログラムを作成してみる. (筆者)


1.プログラムの再考

 まずはリスト1のようなプログラムhello.cを用意しましょう.プログラム内容については説明するまでもないですね(gccではC++スタイルのコメントも使用することができる).それではさっそく,リスト2(a)のようにビルドし,実行してみます.なお,以降の説明で出てくるプログラムサイズやライブラリのバージョン番号は,実行環境によって異なる場合があります.

〔リスト1〕
「Hello, world!」プログラム
#include <stdio.h> // printf()

int main() {
     printf("Hello, world!\n");
      return(123);
    }

〔リスト2〕ビルドと実行 $ gcc -o hello hello.c
$ wc -c hello
      4814 hello
$ ./hello ; echo $?
Hello, world!
123

a)-oオプション以外は付けない

$ gcc -static -o hello-static hello.c
$ wc -c hello-static
  432403 hello-static
$ ./hello-static ; echo $?
Hello, world!
123

b)-staticオプション付き

 「gccでコンパイル」すると,4814バイトの大きさをもつ実行可能ファイルhelloができあがりました〔-oオプションで出力ファイル名を指定している.無指定であればa.out(Assembler OUTput)という名前になる〕.完成したプログラムを実行すると,コンソールに「Hello, world!」が表示され,シェルにはプロセスの終了値として123が返されていることが確認できます($?変数は,直前に実行したプログラムの戻り値が代入される).

 じつは,誰もが気軽に使っている「gccでコンパイルする」という言葉自体が,プログラム開発の正確な理解を妨げる原因になっています.この表現のどこに問題があるのかは,これからしだいに明らかにしていきます.

 さて,現在市販されている教科書のほとんどは,ここで立ち止まることなく文法の説明に進んでしまっているようです.しかし,実際の開発現場で問題となるのは,これほど単純なプログラムのために,なぜ4814バイトもの資源が必要とされるの

か,このプログラムを実行させるために必要なものは何なのかという点ではないでしょうか.本章では,従来見すごされてきたこれらの問題点について検証します.手始めに,先ほどのgccコマンド行に-staticというオプションを加えてみます〔リスト2(b)〕.

 これは文字どおり「静的リンク」を行うためのオプションです.このオプションが付くだけでファイルサイズが一気に432Kバイトに達してしまいました.驚くべきことに90倍も肥大化しているのです.まったく同じ作業をするために必要なリソースが一気に90倍とは,どういうことを意味しているのでしょうか.file コマンドで両者の正体を比較してみましょう(リスト3).

〔リスト3〕
動的リンクプログラムと静的リンクプログラムの比較
$ file hello
hello: ELF 32-bit LSB executable, Intel 80386, version 1, dynamically linked (uses shared libs), not stripped
$ file hello-static
hello-static: ELF 32-bit LSB executable, Intel 80386, version 1, statically linked, not stripped

 fileコマンドによると最初のhelloは,「共有ライブラリを用いて動的にリンク」しており,2番目のhello-staticは,「静的にリンク」していることがわかります.両者のプログラムに共通しているのは,「ライブラリを必要としている」という点です.

 fopen/fread/fcloseなど頻用される関数群はライブラリとして,すべてのプログラムから共有されますが,この共有方法には2種類あります.一つは「静的リンク」と呼ばれる方法で,各々のプログラムに必要な関数ルーチンをライブラリの中から抜き出し,本体にリンクさせる形式です.昔はこの方法が一般的でしたが,プログラムの種類が増えるにつれ,まったく同じ関数のコピーがファイルやメモリ領域で増殖する無駄が生じました.そこで,貴重な資源を節約するために(昔はハードディスクやメモリはCPU以上に高価だった),同一の関数を仮想メモリ上で複数のプログラムから共有するという概念が生まれました.これが現代のPC-UNIXに採用されている共有ライブラリと呼ばれる「動的リンク」形式です(図1).

〔図1〕
静的リンクと動的リンク


インデックス
序章
 1.PC-UNIXの普及と従来型パッケージの限界
 2.Linuxの理解をはばむもの
 3.本質を見極めよう
Chapter1
 1.プログラムの再考
 2.共有ライブラリの正体

今月号特集トップページへ戻る


Copyright 2002 西田 亙