本文主要探讨210的busybox相关知识。
busybox初移植
修改Makefile
ARCH = arm
CROSS_COMPILE = /root/arm-2009q3/bin//arm-none-linux-gnueabi-
配置修改
make menuconfig
Busybox Settings--->
Build Options--->
[*]Build BusyBox as a static binary(no shared libs)
Busybox Library Tuning--->
[*]vi-style line editing commands
[*]Fancy shell prompts
Linux Module Utilities--->
[ ]Simplified modutils
[*]insmod
[*]rmmod
[*]lsmod
[*]modprobe
[*]depmod
Linux System Utilities--->[*]mdev
[*]Support /etc/mdev.conf
[*]Support subdirs/symlinks
[*]Support regular expressions substitutions when renaming dev
[*]Support command execution at device addition/removal
[*]Support loading of firmwares
Coreutils --->
[ ] sync
编译安装
make -j 8 && make install -j 8
结果显示
挂载根文件系统/linuxrc成功,找不到/etc/init.d/rcS和/dev/tty2等文件
busybox再移植
inittab
inittab是etc下的配置文件,linuxrc运行时调用并且按格式解析文件。
inittab格式:
id:runlevels:action:process
#注释
:分隔符
unlevels:程序运行级别(15)
process为可执行程序(shell)
action是process的执行条件
添加inittab
cd rootfs
mkdir etc
cd etc
vim inittab
#first:run the system script file
::sysinit:/etc/init.d/rcS
::askfirst:-/bin/sh
::ctrlaltdel:-/sbin/reboot
#umount all filesystem
::shutdown:/bin/umount -a -r
#restart init process
::restart:/sbin/init
busybox(C)
busybox入口是libbb/appletlib.c的main
其余xxx_main函数为shell命令数主函数
#if ENABLE_BUILD_LIBBUSYBOX
int lbb_main(char **argv)
#else
int main(int argc UNUSED_PARAM, char **argv)
#endif
{
/* Tweak malloc for reduced memory consumption */
#ifdef M_TRIM_THRESHOLD
/* M_TRIM_THRESHOLD is the maximum amount of freed top-most memory
* to keep before releasing to the OS
* Default is way too big: 256k
*/
mallopt(M_TRIM_THRESHOLD, 8 * 1024);
#endif
#ifdef M_MMAP_THRESHOLD
/* M_MMAP_THRESHOLD is the request size threshold for using mmap()
* Default is too big: 256k
*/
mallopt(M_MMAP_THRESHOLD, 32 * 1024 - 256);
#endif
#if !BB_MMU
/* NOMMU re-exec trick sets high-order bit in first byte of name */
if (argv[0][0] & 0x80) {
re_execed = 1;
argv[0][0] &= 0x7f;
}
#endif
#if defined(SINGLE_APPLET_MAIN)
/* Only one applet is selected in .config */
if (argv[1] && is_prefixed_with(argv[0], "busybox")) {
/* "busybox
busybox执行main函数判断argv[0]再调用相应的xxx_main实现命令
lbb_prepare("busybox" IF_FEATURE_INDIVIDUAL(, argv));
applet_name = argv[0];
if (applet_name[0] == '-')
applet_name++;
applet_name = bb_basename(applet_name);
parse_config_file(); /* ...maybe, if FEATURE_SUID_CONFIG */
run_applet_and_exit(applet_name, argv);
/*bb_error_msg_and_die("applet not found"); - sucks in printf */
full_write2_str(applet_name);
full_write2_str(": applet not found\n");
/* POSIX: "If a command is not found, the exit status shall be 127" */
exit(127);
parse_inittab(init.c)函数解析/etc/inittab再执行sysinit,wait,once后死循环执行respwan和askfirst
static void parse_inittab(void)
{
#if ENABLE_FEATURE_USE_INITTAB
char *token[4];
parser_t *parser = config_open2("/etc/inittab", fopen_for_read);
if (parser == NULL)
#endif
{
/* No inittab file - set up some default behavior */
/* Sysinit */
new_init_action(SYSINIT, INIT_SCRIPT, "");
/* Askfirst shell on tty1-4 */
new_init_action(ASKFIRST, bb_default_login_shell, "");
//TODO: VC_1 instead of ""? "" is console -> ctty problems -> angry users
new_init_action(ASKFIRST, bb_default_login_shell, VC_2);
new_init_action(ASKFIRST, bb_default_login_shell, VC_3);
new_init_action(ASKFIRST, bb_default_login_shell, VC_4);
/* Reboot on Ctrl-Alt-Del */
new_init_action(CTRLALTDEL, "reboot", "");
/* Umount all filesystems on halt/reboot */
new_init_action(SHUTDOWN, "umount -a -r", "");
/* Swapoff on halt/reboot */
new_init_action(SHUTDOWN, "swapoff -a", "");
/* Restart init when a QUIT is received */
new_init_action(RESTART, "init", "");
return;
}
#if ENABLE_FEATURE_USE_INITTAB
/* optional_tty:ignored_runlevel:action:command
* Delims are not to be collapsed and need exactly 4 tokens
*/
while (config_read(parser, token, 4, 0, "#:",
PARSE_NORMAL & ~(PARSE_TRIM | PARSE_COLLAPSE))) {
/* order must correspond to SYSINIT..RESTART constants */
static const char actions[] ALIGN1 =
"sysinit\0""wait\0""once\0""respawn\0""askfirst\0"
"ctrlaltdel\0""shutdown\0""restart\0";
int action;
char *tty = token[0];
if (!token[3]) /* less than 4 tokens */
goto bad_entry;
action = index_in_strings(actions, token[2]);
if (action < 0 || !token[3][0]) /* token[3]: command */
goto bad_entry;
/* turn .*TTY -> /dev/TTY */
if (tty[0]) {
tty = concat_path_file("/dev/", skip_dev_pfx(tty));
}
new_init_action(1 << action, token[3], tty);
if (tty[0])
free(tty);
continue;
bad_entry:
message(L_LOG | L_CONSOLE, "Bad inittab entry at line %d",
parser->lineno);
}
config_close(parser);
#endif
}
int init_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE;
int init_main(int argc UNUSED_PARAM, char **argv)
{
if (argv[1] && strcmp(argv[1], "-q") == 0) {
return kill(1, SIGHUP);
}
#if DEBUG_SEGV_HANDLER
{
struct sigaction sa;
memset(&sa, 0, sizeof(sa));
sa.sa_sigaction = handle_sigsegv;
sa.sa_flags = SA_SIGINFO;
sigaction(SIGSEGV, &sa, NULL);
sigaction(SIGILL, &sa, NULL);
sigaction(SIGFPE, &sa, NULL);
sigaction(SIGBUS, &sa, NULL);
}
#endif
if (!DEBUG_INIT) {
/* Expect to be invoked as init with PID=1 or be invoked as linuxrc */
if (getpid() != 1
&& (!ENABLE_FEATURE_INITRD || applet_name[0] != 'l') /* not linuxrc? */
) {
bb_error_msg_and_die("must be run as PID 1");
}
#ifdef RB_DISABLE_CAD
/* Turn off rebooting via CTL-ALT-DEL - we get a
* SIGINT on CAD so we can shut things down gracefully... */
reboot(RB_DISABLE_CAD); /* misnomer */
#endif
}
/* If, say, xmalloc would ever die, we don't want to oops kernel
* by exiting.
* NB: we set die_func *after* PID 1 check and bb_show_usage.
* Otherwise, for example, "init u" ("please rexec yourself"
* command for sysvinit) will show help text (which isn't too bad),
* *and sleep forever* (which is bad!)
*/
die_func = sleep_much;
/* Figure out where the default console should be */
console_init();
set_sane_term();
xchdir("/");
setsid();
/* Make sure environs is set to something sane */
putenv((char *) "HOME=/");
putenv((char *) bb_PATH_root_path);
putenv((char *) "SHELL=/bin/sh");
putenv((char *) "USER=root"); /* needed? why? */
if (argv[1])
xsetenv("RUNLEVEL", argv[1]);
#if !ENABLE_FEATURE_EXTRA_QUIET
/* Hello world */
message(L_CONSOLE | L_LOG, "init started: %s", bb_banner);
#endif
#endif
/* Check if we are supposed to be in single user mode */
if (argv[1]
&& (strcmp(argv[1], "single") == 0 || strcmp(argv[1], "-s") == 0 || LONE_CHAR(argv[1], '1'))
) {
/* ??? shouldn't we set RUNLEVEL="b" here? */
/* Start a shell on console */
new_init_action(RESPAWN, bb_default_login_shell, "");
} else {
/* Not in single user mode - see what inittab says */
/* NOTE that if CONFIG_FEATURE_USE_INITTAB is NOT defined,
* then parse_inittab() simply adds in some default
* actions (i.e., INIT_SCRIPT and a pair
* of "askfirst" shells) */
parse_inittab();
}
#if ENABLE_SELINUX
if (getenv("SELINUX_INIT") == NULL) {
int enforce = 0;
putenv((char*)"SELINUX_INIT=YES");
if (selinux_init_load_policy(&enforce) == 0) {
BB_EXECVP(argv[0], argv);
} else if (enforce > 0) {
/* SELinux in enforcing mode but load_policy failed */
message(L_CONSOLE, "can't load SELinux Policy. "
"Machine is in enforcing mode. Halting now.");
return EXIT_FAILURE;
}
}
#endif
/* Make the command line just say "init" - thats all, nothing else */
strncpy(argv[0], "init", strlen(argv[0]));
/* Wipe argv[1]-argv[N] so they don't clutter the ps listing */
while (*++argv)
nuke_str(*argv);
/* Set up signal handlers */
if (!DEBUG_INIT) {
struct sigaction sa;
/* Stop handler must allow only SIGCONT inside itself */
memset(&sa, 0, sizeof(sa));
sigfillset(&sa.sa_mask);
sigdelset(&sa.sa_mask, SIGCONT);
sa.sa_handler = stop_handler;
/* NB: sa_flags doesn't have SA_RESTART.
* It must be able to interrupt wait().
*/
sigaction_set(SIGTSTP, &sa); /* pause */
/* Does not work as intended, at least in 2.6.20.
* SIGSTOP is simply ignored by init:
*/
sigaction_set(SIGSTOP, &sa); /* pause */
/* These signals must interrupt wait(),
* setting handler without SA_RESTART flag.
*/
bb_signals_recursive_norestart(0
+ (1 << SIGINT) /* Ctrl-Alt-Del */
+ (1 << SIGQUIT) /* re-exec another init */
#ifdef SIGPWR
+ (1 << SIGPWR) /* halt */
#endif
+ (1 << SIGUSR1) /* halt */
+ (1 << SIGTERM) /* reboot */
+ (1 << SIGUSR2) /* poweroff */
#if ENABLE_FEATURE_USE_INITTAB
+ (1 << SIGHUP) /* reread /etc/inittab */
#endif
, record_signo);
}
/* Now run everything that needs to be run */
/* First run the sysinit command */
run_actions(SYSINIT);
check_delayed_sigs();
/* Next run anything that wants to block */
run_actions(WAIT);
check_delayed_sigs();
/* Next run anything to be run only once */
run_actions(ONCE);
/* Now run the looping stuff for the rest of forever.
*/
while (1) {
int maybe_WNOHANG;
maybe_WNOHANG = check_delayed_sigs();
/* (Re)run the respawn/askfirst stuff */
run_actions(RESPAWN | ASKFIRST);
maybe_WNOHANG |= check_delayed_sigs();
/* Don't consume all CPU time - sleep a bit */
sleep(1);
maybe_WNOHANG |= check_delayed_sigs();
/* Wait for any child process(es) to exit.
*
* If check_delayed_sigs above reported that a signal
* was caught, wait will be nonblocking. This ensures
* that if SIGHUP has reloaded inittab, respawn and askfirst
* actions will not be delayed until next child death.
*/
if (maybe_WNOHANG)
maybe_WNOHANG = WNOHANG;
while (1) {
pid_t wpid;
struct init_action *a;
/* If signals happen _in_ the wait, they interrupt it,
* bb_signals_recursive_norestart set them up that way
*/
wpid = waitpid(-1, NULL, maybe_WNOHANG);
if (wpid <= 0)
break;
a = mark_terminated(wpid);
if (a) {
message(L_LOG, "process '%s' (pid %d) exited. "
"Scheduling for restart.",
a->command, wpid);
}
/* See if anyone else is waiting to be reaped */
maybe_WNOHANG = WNOHANG;
}
} /* while (1) */
}
/etc/init.d/rcS
PATH定义程序路径,export导出为环境变量,默认为/bin /sbin /usr/bin /usr/sbin
runleve运行模式,S为单用户模式
umask是用户在创建文件时的默认权限,umask值与文件权限互补
mount -a是挂载/etc/fstab文件中的所有挂载
mdev(udev/mdev)是linux启动时配合驱动生成/dev下的设备文件
hostname指定主机名
ifconfig指定ip地址
添加rcs
cd rootfs/etc
mkdir init.d
cd init.d
vim rcS
#!/bin/sh
PATH=/sbin:/bin:/usr/sbin:/usr/bin
runlevel=S
prevlevel=N
umask 022
export PATH runlevel prevlevel
mount -a
echo /sbin/mdev > /proc/sys/kernel/hotplug
mdev -s
/bin/hostname -F /etc/sysconfig/hostname
ifconfig eth0 192.168.100.27
chmod +x rcS
添加fastab
cd etc
vim fastab
# /etc/fstab: static file system information.
#
# Use 'vol_id --uuid' to print the universally unique identifier for a
# device; this may be used with UUID= as a more robust way to name devices
# that works even if disks are added and removed. See fstab(5).
#
#
proc /proc proc defaults 0 0
sysfs /sys sysfs defaults 0 0
tmpfs /var tmpfs defaults 0 0
tmpfs /tmp tmpfs defaults 0 0
tmpfs /dev tmpfs defaults 0 0
cd rootfs
mkdir proc sys var tmp dev root
添加主机名
cd rootfs/etc
mkdir sysconfig
cd sysconfig
vim hostname
cxb210
添加用户登录
用户登录在inittab执行/bin/sh生成shell界面,故添加/bin/login或/sbin/gettty登录功能
vim etc/inittab
#::askfirst:-/bin/sh
s3c2410_serial2::sysinit:/bin/login
添加passwd和shadow文件
vim etc/passwd
root:x:0:0:root:/root:/bin/sh
vim etc/shadow(123456)
root:$6$xHD0aja9$Bxg0rl3jJCq7RXnUuCaBNZGXC5aZrKWUHCiE0Lgp3vh6.S.4gsMhfPLVSwOwIDVZDNVhjksB0VdcvI7MDTKaz0:19612:0:99999:7:::
profile文件(/etc/)修改提示符号,导出环境变量
vim etc/profile
# Ash profile
# vim: syntax=sh
# No core files by default
ulimit -S -c 0 > /dev/null 2>&1
USER="`id -un`"
LOGNAME=$USER
PS1='[\u@\h \W]\# '
PATH=$PATH
HOSTNAME=`/bin/hostname`
export USER LOGNAME PS1 PATH
添加库文件
未添加库文件210可执静态链接行程序,添加库文件可执行动态链接程序
mkdir /root/rootfs/lib/
cp /root/arm-2009q3/arm-none-linux-gnueabi/libc/lib/*so* /root/rootfs/lib/ -rdf
库文件添加测试
mkdir /root/c
cd c
vim hello.c
#include
int main()
{
printf("hello word\n");
return 0;
}
arm-linux-gcc hello.c -o hello_dynamic
arm-linux-gcc hello.c -o hello_satic -static
cp ./* rootfs/root
添加开机自启动(末尾添加)
vim etc/init.d/rcS
./root/hello_satic
./root/hello_dynamic
制作镜像
mkdir /root/make_image
cd /root/make_image
dd if=/dev/zero of=rootfs.ext2 bs=1024 count=10240
losetup /dev/loop1 rootfs.ext2
mke2fs -m 0 /dev/loop1 10240
mount -t ext2 /dev/loop1 /mnt
cp /root/rootfs/* /mnt -rf
umount /dev/loop1
losetup -d /dev/loop1
烧录并启动
uboot:
set bootargs console=ttySAC2,115200 root=/dev/mmcblk0p2 rw init=/linuxrc rootfstype=ext2
save
fastboot
windows:
fastboot flash system rootfs.ext2
fastboot reboot
结果显示