向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" 需要注意的是这 ...
随机推荐
- 痞子衡嵌入式:飞思卡尔i.MX RTyyyy系列MCU启动那些事(1)- Boot简介
大家好,我是痞子衡,是正经搞技术的痞子.今天痞子衡给大家介绍的是飞思卡尔i.MX RTyyyy系列MCU的BootROM功能简介. 截止目前为止i.MX RTyyyy系列已公布的芯片有三款i.MXRT ...
- sklearn集成支持向量机svm.SVC参数说明
经常用到sklearn中的SVC函数,这里把文档中的参数翻译了一些,以备不时之需. 本身这个函数也是基于libsvm实现的,所以在参数设置上有很多相似的地方.(PS: libsvm中的二次规划问题的解 ...
- How to: Initialize Business Objects with Default Property Values in XPO 如何:在 XPO 中用默认属性值初始化业务对象
When designing business classes, a common task is to ensure that a newly created business object is ...
- 发送RCS成功的消息log_1
//12-02 16:39:00.869323 24174 27394 I CarrierServices: [1172] cpb.x: Send INVITE//12-02 16:39:00.920 ...
- 团队项目之Scrum3
小组:BLACK PANDA 时间:2019.11.23 每天举行站立式会议 提供当天站立式会议照片一张 2 昨天已完成的工作 2 完善用户注册的 ...
- SQL Server之批量清理数据库的死锁
DECLARE killspid CURSOR FOR (SELECT CONVERT(VARCHAR(100), request_session_id) FROM sys.dm_tran_l ...
- 12C新功能:在线移动数据文件 (Doc ID 1566797.1)
12C New Feature : Move a Datafile Online (Doc ID 1566797.1) APPLIES TO: Oracle Database - Enterprise ...
- OAuthon2.0机制详解
最近在忙企业微信和钉钉的第三方应用开发,需要获取一些信息,第一个就是这个OAuthon2.0,先详细了解下概念和流程 一.应用场景 我们要想用第三方播放器播放你的云盘账号里面的一些秘密视频资源,为了要 ...
- Self Service Password 密码策略
1.在活动目录中新建一个用户,并赋予域管理员权限:2.拷贝conf目录下的config.inc.php为config.inc.local.php:3.按自己的实际情况及要求修改config.inc.l ...
- Unity3D 截取6面图 做全景图脚本
using System.Collections;using System.Collections.Generic;using UnityEditor;using UnityEngine; publi ...