本文共 2740 字,大约阅读时间需要 9 分钟。
浅析busybox查找命令和调用相应命令函数的实现流程框架 libbb/appletlib.c =>main =>applet_name = argv[0];//如果为符号链接,比如ln -s busybox ls,那么argv[0]就等于"ls" =>applet_name = bb_basename(applet_name);//去掉绝对路径的'/‘,返回实际找到文件名给applet_name =>parse_config_file();//调用libbb/appletlib.c中的函数 =>run_applet_and_exit run_applet_and_exit =>find_applet_by_name调用的是libbb/appletlib.c中的函数, =>使用bsearch库函数,二分法、折半查找转换后的argv[0]是否为命令,因为busybox可能是经过ln符号链接了的命令,比如ln -s busybox vi void FAST_FUNC run_applet_and_exit(const char *name, char **argv) { int applet = find_applet_by_name(name); if (applet >= 0)//name就是命令,那么说明一定是ln -s符号链接了的命令,那么直接执行[luther.gliethttp] run_applet_no_and_exit(applet, argv); if (!strncmp(name, "busybox", 7)) exit(busybox_main(argv));//执行到这里说明是以busybox ls方式传递的命令. } busybox_main =>如果输入的为 busybox --install -s 创建所有命令的符号链接 busybox --install -h 创建所有命令的硬链接 =>autoconf.h配置文件中指定 #define CONFIG_BUSYBOX_EXEC_PATH "/proc/self/exe" const char bb_busybox_exec_path[] ALIGN1 = CONFIG_BUSYBOX_EXEC_PATH; install_links(busybox, argv[2] && strcmp(argv[2], "-s") == 0); static void install_links(const char *busybox, int use_symbolic_links) { /* directory table * this should be consistent w/ the enum, * busybox.h::bb_install_loc_t, or else... */ static const char usr_bin [] ALIGN1 = "/usr/bin"; static const char usr_sbin[] ALIGN1 = "/usr/sbin"; static const char *const install_dir[] = { &usr_bin [8], /* "", equivalent to "/" for concat_path_file() */ &usr_bin [4], /* "/bin" */ &usr_sbin[4], /* "/sbin" */ usr_bin, usr_sbin }; int (*lf)(const char *, const char *); char *fpc; unsigned i; int rc; lf = link;a//库函数-硬链接 if (use_symbolic_links) lf = symlink;//库函数-符号链接 for (i = 0; i < ARRAY_SIZE(applet_main); i++) { fpc = concat_path_file( install_dir[APPLET_INSTALL_LOC(i)], //根据busybox默认的策略,计算第i个命令所应对应的安装目录[luther.gliethttp] APPLET_NAME(i)); // debug: bb_error_msg("%slinking %s to busybox", // use_symbolic_links ? "sym" : "", fpc); rc = lf(busybox, fpc);//创建之 if (rc != 0 && errno != EEXIST) { bb_simple_perror_msg(fpc); } free(fpc); } } =>run_applet_no_and_exit =>exit(applet_main[applet_no](argc, argv));最终执行命令函数 void FAST_FUNC run_applet_no_and_exit(int applet_no, char **argv) { int argc = 1; while (argv[argc])//因为前面做了argv++的调整,所以这里做一次动态计算argc值 argc++; /* Reinit some shared global data */ xfunc_error_retval = EXIT_FAILURE; applet_name = APPLET_NAME(applet_no); if (argc == 2 && strcmp(argv[1], "--help") == 0) { /* Special case. POSIX says "test --help" * should be no different from e.g. "test --foo". */ //TODO: just compare applet_no with APPLET_NO_test if (!ENABLE_TEST || strcmp(applet_name, "test") != 0) bb_show_usage(); } if (ENABLE_FEATURE_SUID) check_suid(applet_no); exit(applet_main[applet_no](argc, argv));//好了执行applet_main命令数组中对应的处理函数[luther.gliethttp]. }
转载地址:http://lbkci.baihongyu.com/