Busybox 简单解析

BusyBox 简单解析

Busybox 作为一个简易的Linux 命令集,因为其小巧简便,在Linux嵌入式系统中应该颇为广泛,人送外号瑞士军刀。

Busybox也并非将所有命令的可执行程序进行了打包,对其实现也比较感兴趣,就翻了一下源码。

Busybox 工具的使用方式有两种,一种是将命令作为一个参数传入,例如: busybox ls, 而另外一种是将对应的命令直接软连接到busybox


BusyBox 实现的核心机制

Busybox的实现依赖于两个点:

  • 通过读取执行程序时传入的参数表,来进行灵活处理。因为busybox有两种使用方法,故在解析之初会查看agrv[0]是否匹配busybox,以决定是哪种调用方式。
  • Busybox当中自然包含了常见Linux命令的简单实现,但并不是应用的简单打包,而是通过一个颇为庞大的函数指针列表来实现具体的函数调用,譬如说ls_main。

BusyBox 两个Structure

Note: 代码的分析基于Busybox的2.16版本

File name: applet_tables.h
const char applet_names[] ALIGN1 = ""
"[" "\0"
"[[" "\0"
"addgroup" "\0"
"adduser" "\0"
"adjtimex" "\0"
"ar" "\0"
"arp" "\0"
"arping" "\0"
"ash" "\0"
...;

int (*const applet_main[])(int argc, char **argv) = {
test_main,
test_main,
addgroup_main,
adduser_main,
adjtimex_main,
ar_main,
arp_main,
arping_main,
ash_main,
awk_main,
basename_main,
beep_main,
blkid_main,
brctl_main,
...

第一个结构体的作用在于当获取到程序传入的参数表,检查要执行的Linux命令是否在我们的applet_name当中,即查看是否在我们支持的命令集当中,如果支持,则调用第二个数组当中对应的函数指针,去完成与之相对应的Linux命令。

Code

入口位于libbb/appletlib.c
main
{
    ...
    applet_name = bb_basename(applet_name); //  Here applet_name is argv[0], 做转换的原因是考虑到路径的存在
    run_applet_and_exit(applet_name, argv);
    ...
}

void FAST_FUNC run_applet_and_exit(const char *name, char **argv)
{
    int applet = find_applet_by_name(name); // Will check applet_name table.
    if (applet >= 0)
        run_applet_no_and_exit(applet, argv);   // ls --> Hit here.
    if (!strncmp(name, "busybox", 7))
        exit(busybox_main(argv));      // Busybox ls , Hit here.
}

//One easy Loop for  applet_names.
int FAST_FUNC find_applet_by_name(const char *name)
{
#if NUM_APPLETS > 8
    /* Do a binary search to find the applet entry given the name. */
    const char *p;
    p = bsearch(name, applet_names, ARRAY_SIZE(applet_main), 1, applet_name_compare);
    if (!p)
        return -1;
    return p - applet_names;
#else
    /* A version which does not pull in bsearch */
    int i = 0;
    const char *p = applet_names;
    while (i < NUM_APPLETS) {
        if (strcmp(name, p) == 0)
            return i;
        p += strlen(p) + 1;
        i++;
    }
    return -1;
#endif
}

void FAST_FUNC run_applet_no_and_exit(int applet_no, char **argv)
{
    int argc = 1;

    while (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));**  // Hit here, such as ls_main, cat_main.
}

/* If we were called as "busybox..." */
static int busybox_main(char **argv)
{
... some paresr work...
    applet_name = bb_get_last_path_component_nostrip(argv[0]);
    run_applet_and_exit(applet_name, argv);
}

原文地址:https://www.cnblogs.com/johnson37/p/8890950.html

时间: 2024-10-10 07:01:46

Busybox 简单解析的相关文章

ngx lua模块源码简单解析

ngx lua模块源码简单解析分类: nginx 2014-07-11 11:45 2097人阅读 评论(0) 收藏 举报nginxlua数据结构架构目录(?)[+]对nginx lua模块的整个流程,原理简单解析.由于nginx lua模块相关配置,指令,API非常多,所以本文档只以content_by_lua指令举例说明. 读本文档最好配合读源码. 不适合对nginx和lua一点都不了解的人看.1.相关配置详细配置见 https://github.com/openresty/lua-ngin

对 cloudwu 简单的 cstring 进行简单解析

题外话 以前也用C写过字符串,主要应用的领域是,大字符串,文件读取方面.写的很粗暴,用的凑合着.那时候看见云风前辈的一个开源的 cstring 串. 当时简单观摩了一下,觉得挺好的.也没细看.过了较长一段时间,想整合一下,将大字符串和云风的cstring 短简单的串合在一起变成一种.但是自己 认真复制了一遍后发现. 1.整合不了 云风(后面都省略前辈二字,觉得云风两个字,就已经帅的不行了)简单cstring.因为处理的领域不一样. 云风的 cstring => String , 而自己写的操作文

SQLServer 原理简单解析

(1) 客户端sqlserver网络接口通过一种网络协议(可以是共享内存:简单高速,客户端和sql server在同一台计算机默认连接方式:TCP/IP:访问sql server最常用的一种协议,客户端指定ip地址和端口号连接到sql server;命名管道:命名管道和TCP/IP协议在体系结构上是类似的,是为局域网设计的,在广域网中速度会慢一些:VIA:虚拟接口适配器,是一种可以让两个系统进行高性能通信的协议,要求通信两端使用特殊的硬件和专门连接)和服务的的SNI建立了一个连接,然后通过网络协

ContextImpl简单解析

ContextImpl是对Context的一个具体实现类,关键方法如下 1 static class ServiceFetcher { 2 int mContextCacheIndex = -1; 3 /** 4 * Main entrypoint; only override if you don't need caching. 5 */ 6 public Object getService(ContextImpl ctx) { 7 ArrayList<Object> cache = ctx

iOS开发-简单解析JSON数据

什么是JSON ? JSON是一种轻量级的数据格式,一般用于数据交互 服务器返回给客户端的数据,一般都是JSON格式或者XML格式(文件下载除外) ? JSON的格式很像OC中的字典和数组 ? {"name" : "Jack", "age" : 10} {"name" : ["jack", "rose", "jim"]} ? 标准JSON格式的注意点: key必须用双

[ 转载 ] Java基础10--关于Object类下所有方法的简单解析

关于Object类下所有方法的简单解析 类Object是类层次结构的根类,是每一个类的父类,所有的对象包括数组,String,Integer等包装类,所以了解Object是很有必要的,话不多说,我们直接来看jdk的源码,开始我们的分析之路 1.hashcode() public native int hashCode();//native说明跟机器有关,跟对象的地址有关 如果我们新建一个类,而hashcode没有被重写的话,那么hashcode返回的值只于对象的地址有关,如果hashcode被重

python之urllib2简单解析HTML页面

一.urllib2简单获取html页面 #!/usr/bin/env python # -*- coding:utf-8 -*- import urllib2 response = urllib2.urlopen('http://www.baidu.com'); html = response.read(); print html 简单的几行代码就能拿到html页面,接下来局势html的解析工作了. 想象很美好,实际操作就出问题了.baidu没有禁止机器人抓取可以正常抓取到页面,但是比如:htt

springmvc(2)Controller源码简单解析

前面简单的分析了一下DispatcherServlet,接下来分析一下Controller,在web的MVC中,Controller就是其中的C,启动的一些页面逻辑处理,页面映射的功能: 首先看看超类: public interface Controller {//处理请求,最后返回一个ModelAndView对象,这里的ModelAndView就是我们前面分析过:在DispatchServlet中的doDispath()这个方法里面//会通过render方法得到ModelAndView对象,如

spring bean源码简单解析

最近在看spring的源码,发现看这个还是有点早,看的很吃力,有多东西还不是很明白,像代理等, 我感觉spring用abstract模板来写主要功能,用接口来拓展功能,用的出神入化,但也让很多简单 的东西变得不那么好懂了,就是写的啰嗦了,个人感觉.下面就是下spring bean源码的学习: private static final Resource RETURNS_NULL_CONTEXT = qualifiedResource(CLASS, "returnsNull.xml");