体験!マイコンボードで組込みLinux

第6回BusyBoxの活用[後編]

前回はBusyBoxの概要について説明しました。今回は実際に自作のアプリケーションをBusyBoxに追加する方法を紹介します。

独自のアプリケーションの追加

組込み対象プログラム

T-SH7706LSRは制御用組込みボードコンピュータであるので、直接にハードウェアを叩きI/O制御をする独自のアプリケーションプログラムを追加しています。

T-SH7706LSRにはLEDが付属していますので、具体的にはT-SH7706LSRにはLEDを点滅させるような直接にハードウェアを叩きI/O制御をする独自のアプリケーションプログラムを追加してみます。もととなるプログラムはリスト1となり、コマンド名はledで、第1引数の回数だけLEDが点滅するという仕様となっています。基本的にはリスト1をBusyBoxに組込むわけですが、このままではBusyBoxに組み込むことができないので、BusyBoxに組み込める形式に変更をします。

リスト1 ledプログラム(元)
 1	#include <sys/types.h>
 2	#include <sys/stat.h>
 3	#include <fcntl.h>
 4	#include <unistd.h>
 5	#include <stdlib.h>
 6	#include <stdio.h>
 7	#include <string.h>
 8	#include <sys/mman.h>
 9	
10	#include <asm/page.h>
11	
12	#define SCPDR	0x136
13	#define LED	0x10
14	
15	int main(int argc, char **argv) {
16		volatile unsigned char	*mmaped;
17		int			fd, i, n;
18	
19		if(argc > 2) return -1;
20		n = 5;
21		if(argc == 2) n = atoi(argv[1]);
22		fd = open("/dev/mem",O_RDWR);
23		if(fd < 0) {
24			fprintf(stderr,"cannot open /dev/mem\n");
25			return 1;
26		}
27		mmaped = (volatile unsigned char*)mmap(0, PAGE_SIZE, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0xa4000000);
28		close(fd);
29		if(mmaped == MAP_FAILED) {
30			fprintf(stderr,"cannot mmap\n");
31			return 1;
32		}
33	
34		for(i = 0;i < n;i++) {
35			mmaped[SCPDR] |= LED;
36			sleep(1);
37			mmaped[SCPDR] &= ~LED;
38			sleep(1);
39		}
40	
41		munmap((char*)mmaped, PAGE_SIZE);
42		return 0;
43	}

個別アーキテクチャに依存するヘッダは別ですが、基本的にはヘッダの定義が不要なので、ヘッダ定義をとり除き、その代わりlibbb.hを定義します。

また、main関数も

コマンド名_main

というように変更し、MAIN_EXTERNALLY_VISIBLE属性を追加します。

戻り値に関してもBusyBoxではいろいろな定義がありますが、成功の値はEXIT_SUCCESS、失敗の値はEXIT_FAILUREとなります。そのようにして変更をしたプログラムがリスト2となります。

リスト2 ledプログラム(修正版)
 1	#include "libbb.h"
 2	#include <asm/page.h>
 3	
 4	#define SCPDR	0x136
 5	#define LED	0x10
 6	
 7	int led_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE;
 8	int led_main(int argc, char **argv) {
 9		volatile unsigned char	*mmaped;
10		int			fd, i, n;
11	
12		if(argc > 2) return EXIT_FAILURE;
13		n = 5;
14		if(argc == 2) n = atoi(argv[1]);
15		fd = open("/dev/mem",O_RDWR);
16		if(fd < 0) {
17			fprintf(stderr,"cannot open /dev/mem\n");
18			return 1;
19		}
20		mmaped = (volatile unsigned char*)mmap(0, PAGE_SIZE, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0xa4000000);
21		close(fd);
22		if(mmaped == MAP_FAILED) {
23			fprintf(stderr,"cannot mmap\n");
24			return 1;
25		}
26	
27		for(i = 0;i < n;i++) {
28			mmaped[SCPDR] |= LED;
29			sleep(1);
30			mmaped[SCPDR] &= ~LED;
31			sleep(1);
32		}
33	
34		munmap((char*)mmaped, PAGE_SIZE);
35		return EXIT_SUCCESS;
36	}

今回はリスト2のプログラムを、BusyBoxの中にmyappsというフォルダを新規作成して入れることにします。

コンパイル構成設定系統

まず、トップフォルダにあるConfig.inでは、カテゴリー分類されたフォルダ内にあるConfig.inを指定する場所に myappsのフォルダを追加します(リスト3⁠⁠。

リスト3 Config.in(追加部分)
〈前略〉

comment "Applets"

source archival/Config.in
source coreutils/Config.in
source console-tools/Config.in
source debianutils/Config.in
source editors/Config.in
source findutils/Config.in
source init/Config.in
source loginutils/Config.in
source e2fsprogs/Config.in
source modutils/Config.in
source util-linux/Config.in
source miscutils/Config.in
source networking/Config.in
source printutils/Config.in
source mailutils/Config.in
source procps/Config.in
source runit/Config.in
source selinux/Config.in
source shell/Config.in
source sysklogd/Config.in

source myapps/Config.in

そして、コンパイル構成設定のメニューはカテゴリー分類されたmyappsフォルダ内である構成設定のメニューをConfig.srcに記述します。内容はリスト4となります。

リスト4 Config.src
 1	#
 2	# For a description of the syntax of this configuration file,
 3	# see scripts/kbuild/config-language.txt.
 4	#
 5	
 6	menu "My Applications"
 7	
 8	INSERT
 9	
10	config LED
11		bool "led"
12		default y
13		help
14		  a simple I/O control program.
15	
16	endmenu

メニュー名はMy ApplicationsでINSERT以下にメニュー内容を記述します。

メニューでのledコマンドの名称はLEDとし、ledコマンドは構成設定で組込みか外すかの選択のみなので、ledコマンドの選択型はboot型とし、デフォルトでは選択とし、最後にヘルプテキストを記述します。

コンパイル実行系統

まず、トップフォルダにあるMakefileではカテゴリー分類されたフォルダ内であるmyappsを追加します(リスト5⁠⁠。

リスト5 Makefileに追加する
〈前略〉
# Objects we will link into busybox / subdirs we need to visit
core-y		:= \
		applets/ \

libs-y		:= \
		archival/ \
		archival/libunarchive/ \
		console-tools/ \
		coreutils/ \
		coreutils/libcoreutils/ \
		debianutils/ \
		e2fsprogs/ \
		editors/ \
		findutils/ \
		init/ \
		libbb/ \
		libpwdgrp/ \
		loginutils/ \
		mailutils/ \
		miscutils/ \
		modutils/ \
		networking/ \
		networking/libiproute/ \
		networking/udhcp/ \
		printutils/ \
		procps/ \
		runit/ \
		selinux/ \
		shell/ \
		sysklogd/ \
		util-linux/ \
		util-linux/volume_id/ \
		myapps/ \

endif # KBUILD_EXTMOD
〈後略〉

そして、コンパイル実行内容はカテゴリー分類されたmyappsフォルダ内であるコンパイル実行内容をKbuild.srcに記述し、内容はリスト6となります。

リスト6
 1	# Makefile for busybox
 2	#
 3	# Copyright (C) 1999-2005 by Erik Andersen <[email protected]>
 4	#
 5	# Licensed under the GPL v2, see the file LICENSE in this tarball.
 6	
 7	lib-y:=
 8	
 9	INSERT
10	
11	lib-$(CONFIG_LED) += led.o

コンパイル実行内容はオブジェクトファイル名であるled.oのみを追加します。

リンク系統とヘルプテキスト系統

個別のコマンドの実行コードをBusyBox本体にリンクさせるには、BusyBoxソースファイル中のincludeフォルダ内にあるapplets.src.hというファイルにBusyBox本体にリンクさせるための個別のコマンドの実行コードの内容を登録しますので、ledコマンドをアプレットとしてリスト7のようにリンク内容を追加します。

リスト7 applets.src.hの追加部分
〈前略〉
IF_SETARCH(APPLET_ODDNAME(linux64, setarch, _BB_DIR_BIN, _BB_SUID_DROP, linux64))
IF_FEATURE_INITRD(APPLET_ODDNAME(linuxrc, init, _BB_DIR_ROOT, _BB_SUID_DROP, linuxrc))

IF_LED(APPLET(led, _BB_DIR_USR_BIN, _BB_SUID_DROP))

IF_LN(APPLET_NOEXEC(ln, ln, _BB_DIR_BIN, _BB_SUID_DROP, ln))
IF_LOAD_POLICY(APPLET(load_policy, _BB_DIR_USR_SBIN, _BB_SUID_DROP))
〈後略〉

第1引数はコマンド名でそのままledと指定し、第2引数は通常の実行ファイルである _BB_DIR_USR_BIN を指定し、第3引数では特に特権ユーザで実行する必要もないので、_BB_SUID_DROPと指定をします。個別のコマンドのヘルプテキストは、BusyBoxソースファイル中の includeフォルダ内にある usage.src.h というファイルにリスト8のようにヘルプテキスト内容を登録します。

リスト8 ヘルプテキスト追加部分
〈前略〉
#define zcip_full_usage "\n\n" \
       "Manage a ZeroConf IPv4 link-local address\n" \
     "\nOptions:" \
     "\n	-f		Run in foreground" \
     "\n	-q		Quit after obtaining address" \
     "\n	-r 169.254.x.x	Request this address first" \
     "\n	-v		Verbose" \
     "\n" \
     "\nWith no -q, runs continuously monitoring for ARP conflicts," \
     "\nexits only on I/O errors (link down etc)" \

#define led_trivial_usage \
       "[times]\n" \
       "A simple I/O control program"
#define led_full_usage \
       "[times]"


#endif

ledコマンドでは2つのヘルプテキストを記述し、led_trivial_usageは簡単なヘルプテキスト、led_full_usageは詳細なヘルプテキストを記述します。ヘルプテキストが不要であったとしても、このヘルプテキストがないとコンパイルができないので、適当に何らかのテキストを入れるようにしなければなりません。

コンパイル

新規にコマンドを追加した場合は、以下のようにBusyBox自体を再構成しなおします。

make defconfig

あとは従来と同じに作業をします。

構成設定ではledコマンドが追加されたかどうかを以下のようにして確認します。

make menuconfig

トップメニューでは図1のように新規項目である「My Applications」があるかどうかを確認し、そのメニューに入ります。

図1 menuconfigのトップメニュー
画像

そして、図2のように「led」のメニューが選択されていることを確認します。

図2 My Applicationsの中に「led」があることを確認
画像

コンパイルとインストールは以下のようにして作業は終了です。

make
make install

次回は

次回はBusyBoxベースでのネットワーク構築について解説します。

おすすめ記事

記事・ニュース一覧