ACE Service Configurator框架和C语言的“反射”

类别:编程语言 点击:0 评论:0 推荐:

ACE的服务配置框架,是一个非常强大的框架,采用它可以使应用根据相应配置文件进行有选择的服务启动,应用可以重新配置其服务,而无需重新编译或是重新启动应用本身。对于电信领域中的应用,该框架功能确实是非常棒的优点。但是,对于静态类型的服务,也就是说相应的函数是静态的编译到应用中的,ACE一般在主程序中都要用ACE_STATIC_SVC_REQUIRE和ACE_STATIC_SVC_REGISTER来向ACE_Service_Repository登记静态服务,这就造成了主程序和服务之间还存在一定的耦合。当然,对于静态服务这么做没有任何问题。但是,这多多少少让我觉得不爽,这里我是一个极端主义者^_^,我想让我的主程序完全是通过配置文件来启动静态服务的,在代码上主程序和服务完全没有耦合!

在JAVA里,可以通过一个类的名字来获得该类本身。我不太熟悉JAVA^_^,JAVA中的反射大概是这个意思。为了满足上面的要求,主程序完全通过配置文件来启动静态服务,也就是说我们要根据函数的名字来得到相应的函数(对于通过共享库动态加载的服务,我们可以通过dlopen,dlsym等函数,很容易的从函数名字导出函数本身。ACE底层实现,也是通过这样的方式,来动态加载服务的),因此我在标题里写了C语言的“反射”^_^。在C和C++里,我们从语言的角度上,我们没有办法这样做。

俗话说:天无绝人之路。没有C做不到的事情(C是能做到,但是很多时候我做不到,因为我的水平还很差^_^)。这里我们可以通过解析ELF文件格式,很轻松的从函数的名字来得到函数本身,代码如下(该代码只是一个简单的演示):

文件名:parse.c

#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <libelf.h>
#include <gelf.h>

void test(int i)
{
        printf("oh, come on baby\n");
        printf("the i is %d\n",i);
}

int main(int argc, char **argv)
{
        Elf         *elf = NULL;
        Elf_Scn     *scn = NULL;
        GElf_Shdr   shdr;
        Elf_Data    *data = NULL;
        int         fd, ii, count;

        void (*func)(int);

        elf_version(EV_CURRENT);

        fd = open(argv[1], O_RDONLY);
        elf = elf_begin(fd, ELF_C_READ, NULL);

        while ((scn = elf_nextscn(elf, scn)) != NULL) {
                gelf_getshdr(scn, &shdr);
                if (shdr.sh_type == SHT_SYMTAB) {
                 /* found a symbol table, go print it. */
                 break;
                }
        }

        data        = elf_getdata(scn, NULL);
        count       = shdr.sh_size / shdr.sh_entsize;

       
        for (ii=0; ii < count; ++ii) {
                GElf_Sym sym;

                gelf_getsym(data, ii, &sym);
                if(!strcmp("test", elf_strptr(elf, shdr.sh_link, sym.st_name))){
                        func = (void (*)(int))(unsigned long)(sym.st_value& 0xffffffff);//得到函数名字对应的函数地址
                        func(7);
                }
        }

        elf_end(elf);
        close(fd);
}


编译:gcc -o parse parse.c -lelf

运行:parse parse

通过上面这种手段,我们从函数的名字得到了相应的函数。该代码在solaris上编译运行通过。网络上通过解析ELF进行程序hack的例子不少,我这里简单的解析ELF,拿来正道之用,也可谓是名门正派了。(别仍鸡蛋呀^_^)

其实,很多东西就是一种思路,我没有看ACE的时候,从来没有想到过通过配置文件来进行服务的选择启动。当我看了ACE后,就说:“喔,原来程序可以这样”,并且通过自己的发散思维,可以进一步考虑出一些东西。哎。。。,看来自己要学的东西还很多呀,自己还是一个嫩黄瓜^_^。

本文地址:http://com.8s8s.com/it/it28855.htm