busybox学习笔记之一 -- 系统架构

1. build system总体架构
@Makefile
Makefile
+-- include $(srctree)/scripts/Kbuild.include
    #此处将Makefile.build引入主Makefile.
    +-- build := -f $(if $(KBUILD_SRC),$(srctree)/)scripts/Makefile.build obj
+-- -include $(srctree)/arch/$(ARCH)/Makefile


#Makefile.build将各个目录下的Kbuild包含进来.
@scripts/Makefile.build
+-- src := $(obj)
+-- -include .config
+-- include scripts/Kbuild.include
+-- kbuild-dir := $(if $(filter /%,$(src)),$(src),$(srctree)/$(src))
+-- include $(if $(wildcard $(src)/Kbuild), $(src)/Kbuild, \
                $(if $(wildcard $(kbuild-dir)/Kbuild), $(kbuild-dir)/Kbuild, \
                        $(kbuild-dir)/Makefile \
                ) \
        )
+-- include scripts/Makefile.lib

##################################################################################
2. 依赖关系和入口点
#busybox << busybox_unstripped
########################################
busybox: busybox_unstripped
ifeq ($(SKIP_STRIP),y)
        $(Q)cp $< $@
else
        $(Q)$(STRIP) -s --remove-section=.note --remove-section=.comment \
                busybox_unstripped -o $@
# strip is confused by PIE executable and does not set exec bits
        $(Q)chmod a+x $@
endif


#busybox_unstripped << busybox-all
########################################
busybox_unstripped: $(busybox-all) FORCE
        $(call if_changed_rule,busybox__)
        $(Q)rm -f .old_version


#busybox-all <<  $(core-y) $(libs-y)
########################################
# Build busybox
# ---------------------------------------------------------------------------
# busybox is build from the objects selected by $(busybox-init) and
# $(busybox-main). Most are built-in.o files from top-level directories
# in the kernel tree, others are specified in arch/$(ARCH)Makefile.
# Ordering when linking is important, and $(busybox-init) must be first.
#
# busybox
#   ^
#   |
#   +-< $(busybox-init)
#   |   +--< init/version.o + more
#   |
#   +--< $(busybox-main)
#   |    +--< driver/built-in.o mm/built-in.o + more
#   |
#   +-< kallsyms.o (see description in CONFIG_KALLSYMS section)
#
# busybox version (uname -v) cannot be updated during normal
# descending-into-subdirs phase since we do not yet know if we need to
# update busybox.
# Therefore this step is delayed until just before final link of busybox -
# except in the kallsyms case where it is done just before adding the
# symbols to the kernel.
#
# System.map is generated to document addresses of all kernel symbols

busybox-all  := $(core-y) $(libs-y)



#core-y << %/built-in.o
#libs-y << %/lib.a %/built-in.o
#由此可见,core-y和libs-y都是在各自基础上后缀一个built-in.o
########################################## 
core-y          := $(patsubst %/, %/built-in.o, $(core-y))
libs-y1         := $(patsubst %/, %/lib.a, $(libs-y))
libs-y2         := $(patsubst %/, %/built-in.o, $(libs-y))
libs-y          := $(libs-y1) $(libs-y2)



#core-y <<
#libs-y <<
#core-y和libs-y实际上都是一个包含各种目录的字符串.
###########################################
core-y          := \
                applets/ \

libs-y          := \
                archival/ \
                archival/libarchive/ \
                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/ \

#由此可见,按照链接的顺序可以发现,最先执行的代码应该在applets/目录下


@scripts/Kbuild
obj-y :=
obj-y += applets.o

所以,入口点代码应该在applets.c里面

@applets/applets.c
#include "busybox.h"

#if ENABLE_BUILD_LIBBUSYBOX
int main(int argc UNUSED_PARAM, char **argv)
{
        return lbb_main(argv);
}
#endif

3. 代码调用逻辑
int lbb_main(char **argv)
+-- lbb_prepare("busybox" IF_FEATURE_INDIVIDUAL(, argv));
+-- applet_name = argv[0];
+-- applet_name = bb_basename(applet_name);
+-- parse_config_file();
+-- run_applet_and_exit(applet_name, argv);
    +-- int applet = find_applet_by_name(name);
    +-- if (applet >= 0)
            run_applet_no_and_exit(applet, argv);
    +-- if (strncmp(name, "busybox", 7) == 0)
            exit(busybox_main(argv)); //busybox_main()...
+-- full_write2_str(applet_name);
+-- full_write2_str(": applet not found\n");
+-- xfunc_die();


static int busybox_main(char **argv)
+-- applet_name = bb_get_last_path_component_nostrip(argv[0]);
+-- run_applet_and_exit(applet_name, argv);
    +-- int applet = find_applet_by_name(name); //从applet_name[]函数名数组中找到name对应的索引
        +-- const char *p = applet_names;
        +-- while (i < NUM_APPLETS) {
                if (strcmp(name, p) == 0)
                        return i;
                p += strlen(p) + 1;
                i++;
            }
    +-- if (applet >= 0)
            run_applet_no_and_exit(applet, argv);
                     //利用找到的索引在applet_main[]函数指针数组中找到函数指针并执行之
            +-- exit(applet_main[applet_no](argc, argv)); 
    +-- if (strncmp(name, "busybox", 7) == 0)
            exit(busybox_main(argv)); 

以busybox的init为例进行分析:

//通过上面分析可知知道,busybox中使用了applet_names[]和applet_main两个数组来维护busybox应用程序名称和具体应用程序入口点
//之间的映射关系,通过应用程序名在applet_names[]找到应用程序对应的索引,在用这个索引在applet_main[]中找到应用程序的入口点.


const char applet_names[] ALIGN1 = ""
...
"ifconfig" "\0"
"init" "\0"           //init...
"insmod" "\0"
...
};

int (*const applet_main[])(int argc, char **argv) = {
...
ifconfig_main,
init_main,            //init_main...
modprobe_main,
...
};

#root@e4:/sbin# ls -l init
#lrwxrwxrwx    1 311263   named          14 Aug 31 17:12 init -> ../bin/busybox
#/sbin/init实际上是一个指向/bin/busybox的软链接

@init/init.c
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
        ...
        //解析/etc/inittab配置文件
        parse_inittab();
        ...
}



  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值