DirectFB 源码解读之初始化-2

来源:互联网 发布:ecshop数据库表结构 编辑:程序博客网 时间:2024/05/21 22:48
转载时请表明原文出处(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, 它记录了该系统是否支持硬件加速。

原创粉丝点击