浅析busybox查找命令和调用相应命令函数的实现流程框架
2013-01-14 16:52
543 查看
原文: http://blog.chinaunix.net/uid-20564848-id-73422.html
busybox源码学习http://blog.chinaunix.net/uid/20564848/frmd/3729.html
浅析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].
}
busybox源码学习http://blog.chinaunix.net/uid/20564848/frmd/3729.html
浅析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].
}
相关文章推荐
- 浅析busybox查找命令和调用相应命令函数的实现流程框架
- MMS不调用系统函数实现流程
- [转]浅析C++中虚函数的调用及对象的内部布局(利用汇编深刻理解C++虚函数底层实现机制)
- Cocos2D-x精灵的简单实现和函数调用基本流程
- zk框架实现zul的js代码调用服务器java命令
- C语言调用库函数实现二分查找
- C语言调用库函数实现二分查找
- 函数调用的汇编实现浅析
- springMVC框架下如何实现移动端接口调用——流程简介篇
- [转]浅析C++中虚函数的调用及对象的内部布局(利用汇编深刻理解C++虚函数底层实现机制)
- Apache+PHP 实现基于Slim的REST框架 调用系统命令或自己开发的程序
- Linux:使用rpcgen实现64位程序调用32位库函数
- Java实现一个简单的RPC框架(三) 带参数的本地调用
- linux下c程序调用reboot函数实现直接重启
- php闭包实现函数的自调用,也是递归
- C语言拷贝文件函数实现(linux cp [source file] [target file] 命令的实现)
- visual studio下实现图形函数调用
- php中使用exec,system等函数调用系统命令
- C#.NET dll封装(包含UI和实现函数),通过反射调用dll实现控件的快速加载(PrimPointListCreator.cs)