BusyBoxに含まれているアプレットは、1byteでもファイルサイズを小さくするようシンプルにコーディングされていますが、実はさらにサイズを小さくするための仕掛けがBusyBoxには用意されています。
そこで、本連載の最後に、アプレットのファイルサイズを小さくするための2つのテクニックを紹介したいと思います。
シンプルにソースコードを記述するための主な手段として、「シンプルなエラー処理」「シンプルなメッセージ表示」の2つが挙げられます。それぞれについて詳しく見ていきましょう。
・シンプルなエラー処理
一般的なプログラミングでは、エラー処理を丁寧に行うケースがしばしば見受けられます。例えば、ファイルオープンに失敗した場合、
ということをよく行います。
一方、BusyBoxでは、(1)(2)を省略して、いきなり「exit(1)」で終了という処理を行います。この場合、(1)(2)の処理に必要な命令が省略できるため、サイズを抑えることができます。「プログラムが終了すれば、確保されていたリソースもOSにより解放されるため、問題ない」というBusyBoxならではの考え方から、そのような手法が用いられているようです。
図1に、エラー処理の実例を示します。上側のソースコードは、今回移植したソースコードの一部を抜粋したものです。これをBusyBoxらしく書き換えると下側のようになります。
★★チューニング前のソースコード★★ int flash_to_file (int fd,u_int32_t offset,size_t len,const char *filename) { outfd = creat (filename,O_WRONLY); if (outfd < 0) { perror ("creat()"); goto err1; } err1: if (buf != NULL) free (buf); return (1); }
↓
★★チューニング後のソースコード★★ int flash_to_file (int fd,u_int32_t offset,size_t len,const char *filename) { outfd = creat (filename,O_WRONLY); if (outfd < 0) { perror ("creat()"); exit(1); ←エラー時には即exit } (余計なfree処理を省いている) return (1); }
図1 シンプルなエラー処理の例 |
・シンプルなメッセージ表示
コマンドプログラムなどでは、処理の途中経過やエラーメッセージなどを「printf」で表示することがよくあります。しかし、このエラーメッセージ自体は、プログラムの実行ファイルに格納されるため、エラーメッセージの分だけ実行ファイルのサイズが大きくなってしまいます。そこで、BusyBoxでは、このような表示メッセージを省いたり、共通したメッセージを使ったり、あるいは、できるだけ短い文にまとめたりする工夫がなされています。当然ですが、エラーメッセージを1byte小さくできれば、アプレットのサイズも1byte小さくできるのです。
BusyBoxのアプレットの中では、アプレット間で共通して使う関数が定義されている「libbb」の関数群が多用されています。アプレットを書く場合も「libbb」をなるべく使うようにすれば、独自の処理を書かないで済み、ファイルサイズを抑えることができます。また、先ほど挙げたシンプルな処理記述をサポートする関数などが用意されており、「libbb」を使うことで、より効率よくアプレットを記述できます。
「include/libb.h」に関数定義があり、実体は「libbb」ディレクトリで実装されています。ここでは、よく使われる「libbb」の関数として、「x関数」「bb_show_usage」「getopt32」の3つを紹介します。
・x関数
x関数とは、「x<C言語のライブラリ関数名>」という名前で定義された関数群です。主なものとしては、「xopendir」「xmalloc」「xstrdup」「xstrndup」「xmalloc」「xzalloc」「xfopen」「xopen」などがあります。これらは、シンプルなエラー処理とメッセージ表示をサポートする関数群です。例えば、xfopen関数では、ファイルのオープンに失敗すると、"can't open <ファイル名>"と表示し、exit(1)でプログラムを強制終了します。
今回移植した「mtd_debug」アプレットにも以下のようなコードがあります。
if ((fd = open (argv[2],O_SYNC | open_flag)) < 0) { perror ("open()"); exit (1); }
これをx関数である「xopen」関数を使うことで以下の1行で記述できます。
fd = xopen (argv[2],O_SYNC | open_flag);
・bb_show_usage
前回、「usage.h」にアプレットのヘルプ文字列を登録する方法を紹介しました。「bb_show_usage」は、「usage.h」で登録したヘルプ文字列を表示するための関数です。ヘルプの表示は、すべてのアプレットで行う処理であるため、その処理を共通化することでサイズを節約しています。
関数の使い方は、「bb_show_usage()」と記述するだけです。「usage.h」に登録されたアプレットの利用法を表示して終了します。前回、「usage.h」に登録した文字列は空でしたので、空の文字列が表示されます。
今回移植した「mtd_debug」には、「showusage」という関数が定義されていますが、以下のように置き換えることができます。
showusage(progname);
置き換え前: |
↓
bb_show_usage();
置き換え後: |
・getopt32
「getopt32」は、コマンドラインオプションを解釈するための関数です。Linuxでよく使われる「getopt」と似ています。
コマンドライン文字列が「argv」に格納されているとして、
flags = getopt32(argv, “ab”);
とすると、コマンドライン引数に「-a」オプションが渡されたときは、「flags」の1ビット目が「1」となり、「-b」オプションが渡されたときは、「flags」の2ビット目が「1」となります。例えば、「flags」が「2」ならば、「-b」オプションが渡されたことになります。
また、コマンドラインオプションの値を読み込むこともできます。
flags = getopt32(argv, "a:b”, &value);
のように、「a:」とすると、「-a」オプションに値が渡ることを表し、値が「value」に読み込まれます。「getopt32」については、ほかにもさまざまな使い方があります。詳しくは、「libbb/getopt32.c」に書かれていますので、そちらを参考にしてください。
さて、本連載「いますぐ使える! BusyBox活用術」では、駆け足でBusyBoxの適用方法や拡張の仕方について紹介してきました。
本連載の締めくくりに、「BusyBoxのコミュニティ」について少し紹介したいと思います。BusyBoxのコミュニティは、BusyBoxメーリングリストを土台にしており、BusyBoxの開発には誰もが自由に参加でき、追加したアプレットをメーリングリストに提案することもできます。
ご興味のある方はぜひ、メーリングリストに新しいアプレットやバグフィックスを投稿してみてください。世界中の開発者からさまざまなコメントが寄せられ、きっと大いに刺激を受けることができるはずです。筆者の感想ですが、敷居も低く、気楽にメールを投げられる大らかな雰囲気のコミュニティだと思います(例えば、BusyBoxのメンテナ<ソースコード管理人>の転職先募集のメールが流れたりしました)。皆さんの積極的なご参加をお待ちしています!
関連リンク: | |
---|---|
⇒ | BusyBoxメーリングリスト |
最後に、1人でも多くの方がBusyBoxに興味を持ち、そして、実際にBusyBoxの開発に携わるエンジニアとして活躍されることを筆者は願ってやみません。本連載がその一助になれば幸いです。長期間お付き合いいただきありがとうございました。
Copyright © ITmedia, Inc. All Rights Reserved.