根文件系统(二):busybox

        本文主要探讨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_第1张图片

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  " should still work as expected */
        argv++;
    }
    /* applet_names in this case is just "applet\0\0" */
    lbb_prepare(applet_names IF_FEATURE_INDIVIDUAL(, argv));
    return SINGLE_APPLET_MAIN(argc, argv);
#else
    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);
#endif
} 
  

                 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

结果显示 

根文件系统(二):busybox_第2张图片

你可能感兴趣的:(linux,嵌入式硬件,arm开发,c语言)