向busybox中添加自己的applet
关键词: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的更多相关文章
- [转]busybox中telnet 功能添加
使用busybox制作的一个基本根文件系统如何添加telnetd服务呢? 下面把本人的添加过程列出来供大家分享,如有不同意见请不吝赐教! 1. 添加telnet的支持(busybox中配置) Netw ...
- 在jekyll模板博客中添加网易云模块
最近使用GitHub Pages + Jekyll 搭建了个人博客,作为一名重度音乐患者,博客里面可以不配图,但是不能不配音乐啊. 遂在博客里面引入了网易云模块,这里要感谢网易云的分享机制,对开发者非 ...
- 在Linux(Luna)下向Launch启动器中添加图标
记录下在Luna下向Launch中添加图标的步骤,以供以后参考,这里我以加入eclipse图标为例: 首先,我们来创建一个desktop文件(Luna中到启动器Launch可以看作是Ubuntu中到桌 ...
- 用Retrofit发送请求中添加身份验证
用Retrofit发送请求中添加身份验证====================在安卓应用开发中, retrofit可以极大的方便发送http网络请求,不管是GET, POST, 还是PUT, DEL ...
- 在html中添加script脚本的方法和注意事项
在html中添加script脚本有两种方法,直接将javascript代码添加到html中与添加外部js文件,这两种方法都比较常用,大家可以根据自己需要自由选择 在html中添加<script& ...
- MVC学习随笔----如何在页面中添加JS和CSS文件
http://blog.csdn.net/xxjoy_777/article/details/39050011 1.如何在页面中添加Js和CSS文件. 我们只需要在模板页中添加JS和CSS文件,然后子 ...
- 怎样在Windows资源管理器中添加右键菜单以及修改右键菜单顺序
有时,我们需要在Windows资源管理器的右键菜单中添加一些项,以方便使用某些功能或程序. 比如我的电脑上有一个免安装版的Notepad++,我想在所有文件的右键菜单中添加一项用Notepad++打开 ...
- 在WebStorm环境中给nodejs项目中添加packages
照前文 http://www.cnblogs.com/wtang/articles/4133820.html 给电脑设置了WebStorm的IDE的nodejs开发环境.新建了个express的网站 ...
- dotnet webapi 中添加Swagger文档
首先添加"SwaggerGenerator": "1.1.0","SwaggerUi": "1.1.0" 需要注意的是这 ...
随机推荐
- 针对上一篇prim最后的完善结果
edge* Graph::prim(int cur) { if (cur >= this->vertexNum) { return NULL; } int *weight = new in ...
- IT兄弟连 HTML5教程 CSS3属性特效 transition过渡
CSS3的transition允许css的属性值在一定的时间区间内平滑地过渡.这种效果可以在鼠标单击.获得焦点.被点击或对元素任何改变中触发,并圆滑地以动画效果改变CSS的属性值. transitio ...
- ConcurrentHashMap(1.7)分析
1. 先来了解ConcurrentHashMap中的几个成员,当然大多数与HashMap中的相似,我们只看独有的成员 /** * The default concurrency level for ...
- 阿里iconfont的使用
1.找到阿里巴巴图标库 2.找到图标 3.搜索你想要的图标 4.将图标添加到购物车 5.点击右上角的购物车按钮,我这里添加了两个. 6.提示你登陆,不需要花钱,找其中一个账号登陆一下就行了 假如你使用 ...
- Analyze Data 分析数据
In this lesson, you will learn how to add the Analysis functionality to your application. For this p ...
- TCP服务端
出处: https://blog.csdn.net/DGH2430284817/article/details/86653294问题描述: 在用socket的通信中,经常会出现这种情况,客 ...
- 「漏洞预警」Apache Flink 任意 Jar 包上传导致远程代码执行漏洞复现
漏洞描述 Apache Flink是一个用于分布式流和批处理数据的开放源码平台.Flink的核心是一个流数据流引擎,它为数据流上的分布式计算提供数据分发.通信和容错功能.Flink在流引擎之上构建批处 ...
- Linux禁用root用户
在创建各种云主机的时候,云服务商给的都是root用户,这很方便,但是有某些时候会造成一些困扰,日后在服务器上启动各种服务后,仅仅拥有root权限的用户才能访问更改这些服务,这样会造成一些不必要的困扰, ...
- 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 ...
- react 项目引入路由
下载路由包 npm i react-router-dom -d 前台路由 登陆: /login /login.jsx App.js import React ,{Component} from 're ...