您的位置:首页 > 其它

DirectFB 源码解读之初始化-2

2013-03-21 15:48 309 查看
转载时请表明原文出处(http://blog.sina.com.cn/wyw1976)及作者邮箱(wyw1976@gmail.com)

 

 

现在我们开始阅读direct_modules_explore_directory()【lib\direct\Modules. C】.

 

Int direct_modules_explore_directory ( DirectModuleDir *directory )

{

#ifdef DYNAMIC_LINKING

#一般情况下,driver都是以动态链接库的形式存在的

     int            dir_len;

     DIR           *dir;

     struct dirent *entry = NULL;

     struct dirent  tmp;

     int            count = 0;

 

     D_ASSERT( directory != NULL );

     D_ASSERT( directory->path != NULL );

 

     D_DEBUG_AT( Direct_Modules, "%s( '%s' )\n", __FUNCTION__, directory->path );

     dir_len = strlen( directory->path );

#打开目录,path 就是上面宏定义中设定的

     dir     = opendir( directory->path );  

     if (!dir) {

          D_DEBUG_AT( Direct_Modules, "  -> ERROR opening directory: %s!\n", strerror(errno) );

          return 0;

     }

     while (readdir_r( dir, &tmp, &entry ) == 0 && entry)

{

#读取目录下的每一个文件

#opendir, readdir_r等都是c语言中操作目录的函数

 

          void              *handle;

          DirectModuleEntry *module;

          int                entry_len = strlen(entry->d_name);

#只处理后缀是so的文件, 即动态连接库

          if (entry_len < 4 ||

              entry->d_name[entry_len-1] != 'o' ||

              entry->d_name[entry_len-2] != 's')

               continue;

#查看一下这个文件是否已经在链表中了,即这个driver是否已经遍历过了,如果是,则跳过

          if (lookup_by_file( directory, entry->d_name ))

               continue;

 

#为新的module分配一个DirectModuleEntry 的数据结构, 这个结构将来要加入的到链表中

          module = D_CALLOC( 1, sizeof(DirectModuleEntry) );

          if (!module)

               continue;

 

          module->directory = directory;

          module->dynamic   = true;

          module->file      = D_STRDUP( entry->d_name );

 

          directory->loading = module;

 

#打开这个动态链接库, 实际调用的是dlopen。

#需要注意的是这时候这module并没有加入到list中,只是通过directory->loading暂时记录起来。

          if ((handle = open_module( module )) != NULL) {

#如果一切顺利,这个module应该已经注册成功并加入到directory的链表中,而module->loaded 也设为了true,你可能纳闷,因为open_module 中并没有这些代码呀,别急,我们后面会讲

               if (!module->loaded)

              {

                    int    len;

                    void (*func)();

                    #如果进入了这里就意味的module自己注册没有成功,这是需要手动注册。

                    D_ERROR( "Direct/Modules: Module '%s' did not register itself after loading! "

                             "Trying default module constructor...\n", entry->d_name );

 

                    len = strlen( entry->d_name );

                   #去掉后缀“.so”

                    entry->d_name[len-3] = 0;

                       #掉前缀”lib”,例如“libdirectfb_fbdev.so”就变成了”directfb_fbdev”,

 

                    func = dlsym( handle, entry->d_name + 3 );

                      #在动态库中搜索函数directfb_fbdev

                      #可是所有的Fbdev源码中好像并没有directfb_fbdev这个函数的定义,这是怎么回事呢?

                      #原来在libdirectfb_fbdev.so 的源码Fbdev.c 中有个宏定义DFB_CORE_SYSTEM(fbdev),展开这个 宏定义,一切都明白了。而directfb_fbdev实际调用的是direct_modules_register,它的工作就是自动注册的过程,我们在此我详述,稍后会讲

                    if (func)

                     {

                         #执行这个函数, 

                         func();

                         #上述函数执行完毕后,loaded应为true, 否则就意味着注册失败

                          if (!module->loaded)

                           {

                              D_ERROR( "Direct/Modules: ... even did not register after "

                                       "explicitly calling the module constructor!\n" );

                           }

                      }

                      else

                      {

                          #func为NULL, 即不存在构造函数,则什么也不做

                               D_ERROR( "Direct/Modules: ... default contructor not found!\n" );

                      }

                     if (!module->loaded)

                     {

                       #如果手工注册也失败则仍然将该动态链接库加入到链表中,

                       #只不过disabled设为true, 表示不可用

                         module->disabled = true;

                          D_MAGIC_SET( module, DirectModuleEntry );

                         direct_list_prepend( &directory->entries,

                                              &module->link );

                    }

               }

 

               if (module->disabled)

               {

                    #对于状态是disable的module,也就是自动注册和手动注册都没有成功的,则将其关闭

                    dlclose( handle );

                    module->loaded = false;

               }

               else

             {

                  #对于注册成功的module, 记录动态库的handle

                  #以后就可以根据这个handle调用库中的函数了,

                  #注意的是这些动态库是处于打开状态,

                    module->handle = handle;

                    count++;

               }

          }#endif(handle=open_module(…))

          else

          {

              #如果module打开失败,则仍然将其加入链表中,disabled设为true,表示不可用

               module->disabled = true;

               D_MAGIC_SET( module, DirectModuleEntry );

               direct_list_prepend( &directory->entries, &module->link );

          }

 

          directory->loading = NULL;#当前没有试图加载的module,为加载下一个module做准备

     }//endof while(readdir_r)

 

     closedir( dir );

 

     return count;

#else

     return 0;

#endif
}

现在我们解决上一节中那个悬而未决的问题:dlopen()中能够到底做了些什么?

dlopen()是一个标准的C函数,在dlopen()函数说明中有这样一段话:

“Instead, libraries should export routines using the __attribute__((constructor)) and __attribute__((destructor)) function attributes.  See the gcc info pages for information on these.  Constructor routines are executed before dlopen() returns,  and  destructor
 routines  are  executed  before dlclose() returns.”

 

也就是在dlopen()返回前,它将执行动态链接库中被__attribute__((constructor)) 修饰的函数。

 

现在再回头看一下src\core\Core_system.h的定义,确实有一个被__attribute__((constructor))修饰的函数:

#define DFB_CORE_SYSTEM(shortname)                              \

__attribute__((constructor)) void directfb_##shortname( void ); \

                                                                \

void                                                            \

directfb_##shortname( void )                                    \

{                                                               \

     direct_modules_register( &dfb_core_systems,                \

                              DFB_CORE_SYSTEM_ABI_VERSION,      \

                              #shortname, &system_funcs );      \

}

 

不论具体的system是什么(也就是shortname是什么,每个system的实现中都会调用DFB_CORE_SYSTEM这个宏),其最终都会调用direct_modules_register()。

direct_modules_register()【lib\direct\Modules.c】才真正完成将当前module加入各个链表的工作,例如我们当前遍历的system链表,它就将每一个system实现挂在dfb_core_systems这个链表中,同时设置 ‘entry->loaded    = true'表示该module已经加载成功。

 

至此dfb_system_lookup()中direct_modules_explore_directory( &dfb_core_systems )全部完成。这时候实际上所有的system 实现都是打开的同时挂在dfb_core_systems链表中,dfb_system_lookup()根据configure 中指定system 确定最终的选用system是哪个(比较module的名字,上面标红的字段),然后将没用的module关闭。而选中的sytem及其函数表会记录在两个全局变量中:system_module()和system_funcs。

 

另外, 它还会调用system_funcs函数表中的GetSystemInfo(),得到该graphics system 的一些基本信息,这些信息也记录在一个全局变量system_info中, 其实这些信息中我们最关心的就是其中的caps, 它记录了该系统是否支持硬件加速。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: