关键词:buysbox、applet等。

busybox常用于嵌入式环境,集成中断Linux命令和工具。这些工具简单高效。

下面从如下方面了解:

  • 这些命令是一个软链接到busybox,那么是如何从软连接到busybox再到执行相应的功能的?
  • 如何添加自己的applet命令,进而扩展busybox?
  • 以及一个applet是如何嵌入到busybox环境的。

1. 如何从软链接到busybox的applet调用?

在busybox环境中,调用命令比如ls,其实是指向/bin/ls -> busybox的。

那么buysbox又是如何将这个软链接对应的实际功能的呢?

int main(int argc UNUSED_PARAM, char **argv)
{
...
#if defined(SINGLE_APPLET_MAIN)
...
#else lbb_prepare("busybox" IF_FEATURE_INDIVIDUAL(, argv));
# if !ENABLE_BUSYBOX
if (argv[] && is_prefixed_with(bb_basename(argv[]), "busybox"))
argv++;
# endif
applet_name = argv[];
if (applet_name[] == '-')
applet_name++;
applet_name = bb_basename(applet_name);
parse_config_file(); /* ...maybe, if FEATURE_SUID_CONFIG */run_applet_and_exit(applet_name, argv);
#endif
} static NORETURN void run_applet_and_exit(const char *name, char **argv)
{
# if ENABLE_BUSYBOX
if (is_prefixed_with(name, "busybox"))
exit(busybox_main(argv));--------------------------------显示busybox帮助信息、applet列表等。
# endif
# if NUM_APPLETS >
/* find_applet_by_name() search is more expensive, so goes second */
{
int applet = find_applet_by_name(name);------------------根据applet的name找到其在applet_main[]中的序号。
if (applet >= )
run_applet_no_and_exit(applet, name, argv);
}
# endif
...
} static int busybox_main(char **argv)
{
if (!argv[]) {-----------------------------------------------只有busybox情况下,显示帮助信息。
/* Called without arguments */
...
} if (is_prefixed_with(argv[], "--list")) {---------------------busybox --list显示busybox所有applet。
...
}
...
if (strcmp(argv[], "--help") == ) {--------------------------busybox --help显示busybox帮助信息。
/* "busybox --help [<applet>]" */
if (!argv[])
goto help;
/* convert to "<applet> --help" */
argv[] = argv[];
argv[] = NULL;
} else {
/* "busybox <applet> arg1 arg2 ..." */
argv++;
}
/* We support "busybox /a/path/to/applet args..." too. Allows for
* "#!/bin/busybox"-style wrappers */
applet_name = bb_get_last_path_component_nostrip(argv[]);
run_applet_and_exit(applet_name, argv);-----------------------类似于执行busybox ls,然后调用ls applet。
} void FAST_FUNC run_applet_no_and_exit(int applet_no, const char *name, char **argv)
{
...
if (
# if defined APPLET_NO_test
&& applet_no != APPLET_NO_test
# endif
# if defined APPLET_NO_true
&& applet_no != APPLET_NO_true
# endif
# if defined APPLET_NO_false
&& applet_no != APPLET_NO_false
# endif
) {
if (argc == && strcmp(argv[], "--help") == ) {-------如果是applet对应的--help。
/* Make "foo --help" exit with 0: */
xfunc_error_retval = ;
bb_show_usage();
}
}
if (ENABLE_FEATURE_SUID)
check_suid(applet_no);
xfunc_error_retval =applet_main[applet_no](argc, argv);-----根据applet_no好找到对应的函数,比如ls对应ls_main()。
/* Note: applet_main() may also not return (die on a xfunc or such) */
xfunc_die();
} void FAST_FUNC bb_show_usage(void)
{
if (ENABLE_SHOW_USAGE) {
#ifdef SINGLE_APPLET_STR
...
#else
const char *p;
const char *usage_string = p = unpack_usage_messages();
int ap = find_applet_by_name(applet_name);---------------根据全局变量applet_name找到对应的序号,然后根据需要找到对应的usage字符串。 if (ap < ) /* never happens, paranoia */
xfunc_die();
while (ap) {
while (*p++) continue;
ap--;
}
...
}
xfunc_die();
}

2. 如何添加applet

若需要添加自己的applet,比如在miscutils下创建一个monitor.c文件,在include创建一个monitor.h文件。

//config:config MONITOR-----------------------------------------------------Config.src会读取下面内容写入到Config.in中,用于配置monitor功能。
//config: bool "monitor"
//config: default n
//config: select PLATFORM_LINUX
//config: help
//config: Monitor will collect system exception, daemon corruption, critical app exit. //applet:IF_MONITOR(APPLET(monitor, BB_DIR_SBIN, BB_SUID_DROP))--------------此句会写入include/applets.h中,等于是声明了monitor_main()函数。 //kbuild:lib-$(CONFIG_MONITOR) += monitor.o----------------------------------经由Kbuild.src生成写入到Kbuild中,是对是否编译monitor.c的控制。 //usage:#define monitor_trivial_usage----------------------------------------写入到include/usage.h中,是monitor的帮助信息。
//usage: "[-q] [-o OFF] [-f FREQ] [-p TCONST] [-t TICK]"
//usage:#define monitor_full_usage "\n\n"
//usage: "Monitor system or app exception.\n"
//usage: "\n -q Quiet" #include "libbb.h"
#include <syslog.h>
#include <sys/un.h>

上面的config/applet/kbuild/usage,分别生成到miscutils/Config.in、include/applets.h、miscutils/Kbuild、include/usage.h四个文件中。

所以在配置了CONFIG_MONITOR之后,根据miscutils/Kbuild会编译monitor.c,入口函数是monitor_main()。

3. applet是如何嵌入到busybox的?

通过applets/applet_tables.c生成可执行文件applet_tables。

applets/Kbuild中执行cmd_gen_applet_tables = applets/applet_tables include/applet_tables.h include/NUM_APPLETS.h,生成applet_tables.h文件,以及applet总数的NUM_APPLETS定义。

#define NUM_APPLETS 260
#define KNOWN_APPNAME_OFFSETS 8 const uint16_t applet_nameofs[] ALIGN2 = {
,
,
,
,
,
,
,
}; const char applet_names[] ALIGN1 = ""--------------------------------------在find_applet_by_name()等函数中根据applet名称找到applet对应序号。
"[" "\0"
"[[" "\0"
"addgroup" "\0"
"adduser" "\0"
...
"zcat" "\0"
; #define APPLET_NO_addgroup 2
#define APPLET_NO_adduser 3
...
#define APPLET_NO_zcat 259 #ifndef SKIP_applet_main
int (*const applet_main[])(int argc, char **argv) = {---------------------根据applet序号,找到对应的入口函数。
test_main,
test_main,
addgroup_main,
adduser_main,
...
gunzip_main,
};
#endif const uint8_t applet_suid[] ALIGN1 = {
0x00,
0x00,
...0x00,
}; const uint8_t applet_install_loc[] ALIGN1 = {
0x33,
0x44,
...0x13,
};

其他生成文件还包括:usage.h、applets.h等。

usage.h中包含了函数的帮助信息,是由usage.c编译的usage生成的。

#define monitor_trivial_usage \
"[-q] [-o OFF] [-f FREQ] [-p TCONST] [-t TICK]" \ #define monitor_full_usage "\n\n" \
"Monitor system or app exception.\n" \
"\n -q Quiet" \

4. 小结

一个是添加applet的路径,新增.c和.h文件,其中最重要的是.c文件中特殊注释:config:、applet:、kbuild:、usage:。

然后busybox编译系统,解析.c中的注释,并将其添加到include/applets.h、include/usage.h、include/applet_tables.h等文件中。

两一个是applet的执行路径,busybox的入口函数mian()根据传入的applet_name,然后通过find_applet_by_name()找到对应序号,然后执行applet_main[]函数。即完成对applet的调用。

参考文档:《扩充BusyBox,追加Applet的方法》、《如何向busybox添加自己的命令》。

向busybox中添加自己的applet的更多相关文章

  1. [转]busybox中telnet 功能添加

    使用busybox制作的一个基本根文件系统如何添加telnetd服务呢? 下面把本人的添加过程列出来供大家分享,如有不同意见请不吝赐教! 1. 添加telnet的支持(busybox中配置) Netw ...

  2. 在jekyll模板博客中添加网易云模块

    最近使用GitHub Pages + Jekyll 搭建了个人博客,作为一名重度音乐患者,博客里面可以不配图,但是不能不配音乐啊. 遂在博客里面引入了网易云模块,这里要感谢网易云的分享机制,对开发者非 ...

  3. 在Linux(Luna)下向Launch启动器中添加图标

    记录下在Luna下向Launch中添加图标的步骤,以供以后参考,这里我以加入eclipse图标为例: 首先,我们来创建一个desktop文件(Luna中到启动器Launch可以看作是Ubuntu中到桌 ...

  4. 用Retrofit发送请求中添加身份验证

    用Retrofit发送请求中添加身份验证====================在安卓应用开发中, retrofit可以极大的方便发送http网络请求,不管是GET, POST, 还是PUT, DEL ...

  5. 在html中添加script脚本的方法和注意事项

    在html中添加script脚本有两种方法,直接将javascript代码添加到html中与添加外部js文件,这两种方法都比较常用,大家可以根据自己需要自由选择 在html中添加<script& ...

  6. MVC学习随笔----如何在页面中添加JS和CSS文件

    http://blog.csdn.net/xxjoy_777/article/details/39050011 1.如何在页面中添加Js和CSS文件. 我们只需要在模板页中添加JS和CSS文件,然后子 ...

  7. 怎样在Windows资源管理器中添加右键菜单以及修改右键菜单顺序

    有时,我们需要在Windows资源管理器的右键菜单中添加一些项,以方便使用某些功能或程序. 比如我的电脑上有一个免安装版的Notepad++,我想在所有文件的右键菜单中添加一项用Notepad++打开 ...

  8. 在WebStorm环境中给nodejs项目中添加packages

    照前文 http://www.cnblogs.com/wtang/articles/4133820.html  给电脑设置了WebStorm的IDE的nodejs开发环境.新建了个express的网站 ...

  9. dotnet webapi 中添加Swagger文档

    首先添加"SwaggerGenerator": "1.1.0","SwaggerUi": "1.1.0" 需要注意的是这 ...

随机推荐

  1. 针对上一篇prim最后的完善结果

    edge* Graph::prim(int cur) { if (cur >= this->vertexNum) { return NULL; } int *weight = new in ...

  2. IT兄弟连 HTML5教程 CSS3属性特效 transition过渡

    CSS3的transition允许css的属性值在一定的时间区间内平滑地过渡.这种效果可以在鼠标单击.获得焦点.被点击或对元素任何改变中触发,并圆滑地以动画效果改变CSS的属性值. transitio ...

  3. ConcurrentHashMap(1.7)分析

    1.  先来了解ConcurrentHashMap中的几个成员,当然大多数与HashMap中的相似,我们只看独有的成员 /** * The default concurrency level for ...

  4. 阿里iconfont的使用

    1.找到阿里巴巴图标库 2.找到图标 3.搜索你想要的图标 4.将图标添加到购物车 5.点击右上角的购物车按钮,我这里添加了两个. 6.提示你登陆,不需要花钱,找其中一个账号登陆一下就行了 假如你使用 ...

  5. Analyze Data 分析数据

    In this lesson, you will learn how to add the Analysis functionality to your application. For this p ...

  6. TCP服务端

    出处: https://blog.csdn.net/DGH2430284817/article/details/86653294问题描述:       在用socket的通信中,经常会出现这种情况,客 ...

  7. 「漏洞预警」Apache Flink 任意 Jar 包上传导致远程代码执行漏洞复现

    漏洞描述 Apache Flink是一个用于分布式流和批处理数据的开放源码平台.Flink的核心是一个流数据流引擎,它为数据流上的分布式计算提供数据分发.通信和容错功能.Flink在流引擎之上构建批处 ...

  8. Linux禁用root用户

    在创建各种云主机的时候,云服务商给的都是root用户,这很方便,但是有某些时候会造成一些困扰,日后在服务器上启动各种服务后,仅仅拥有root权限的用户才能访问更改这些服务,这样会造成一些不必要的困扰, ...

  9. September 15th, 2019. Sunday, Week 38th.

    Break down these walls and come on in. 一路披荆斩棘,勇往直前. We are the only wall that stands in our way to s ...

  10. react 项目引入路由

    下载路由包 npm i react-router-dom -d 前台路由 登陆: /login /login.jsx App.js import React ,{Component} from 're ...