读书人

cherokee 插件加载器源码辨析

发布时间: 2012-07-30 16:19:05 作者: rapoo

cherokee 插件加载器源码剖析

cherokee 服务器的绝大部分功能都是用插件实现的, 因此要理解cherokee的源码首先需要理解的就是cherokee的插件.

插件相关的主要结构体有以下几个.

?

// 插件, 对应于每个插件typedef struct {cherokee_plugin_type_t    type;void                         *instance;void                         *configure;const char               *name;} cherokee_plugin_info_t;// 插件加载器实体, 对应于每个插件typedef struct {        cherokee_plugin_info_t *info;          // 从动态库中读取的插件info        void                              *dlopen_ref;// dlopen打开的动态链接库        cherokee_boolean_t      built_in;} cherokee_plugin_loader_entry_t;// 插件加载器, 每个Server上只有一个, 对应于每个进程typedef struct {        cherokee_avl_t            table;         // AVL 树包含了所有插件名-实体的键值对        cherokee_buffer_t       module_dir;// 模块目录        cherokee_buffer_t       deps_dir;   // 依赖插件目录} cherokee_plugin_loader_t;

?

插件加载器各部分之间的关系

cherokee 插件加载器源码辨析

?


cherokee 插件加载器源码辨析

?

以下便是插件加载的过程, 注释上已经写得很清楚了.

?

static ret_tget_info (cherokee_plugin_loader_t  *loader,  const char                *module,  int                        flags,  cherokee_plugin_info_t   **info,  void                     **dl_handler){ret_t             ret;cherokee_buffer_t info_name = CHEROKEE_BUF_INIT;/* Build the info struct string */cherokee_buffer_add_va (&info_name, "cherokee_%s_info", module);/* Open it 加载动态链接库到dl_handler */ret = dylib_open (loader, module, flags, dl_handler);if (ret != ret_ok) {cherokee_buffer_mrproper (&info_name);return ret_error;}// 从动态库中读取插件info 结构体(cherokee_plugin_info_t)// *info = get_sym_from_dlopen_handler (*dl_handler, info_name.buf);if (*info == NULL) {cherokee_buffer_mrproper (&info_name);return ret_not_found;}/* Free the info struct string */cherokee_buffer_mrproper (&info_name);return ret_ok;}static ret_tcheck_deps_file (cherokee_plugin_loader_t *loader, const char               *modname){FILE             *file;char              temp[128];cherokee_buffer_t filename = CHEROKEE_BUF_INIT;// 将路径名拷贝到buffer, cherokee_buffer_add_va (&filename, "%s/%s.deps", loader->deps_dir.buf, modname);file = fopen (filename.buf, "r");if (file == NULL)goto exit;while (!feof(file)) {int   len;char *ret;// 读取插件名ret = fgets (temp, 127, file);if (ret == NULL)break;len = strlen (temp);if (len < 2)continue;if (temp[0] == '#')continue;if (temp[len-1] == '\n')temp[len-1] = '\0';// 加载插件cherokee_plugin_loader_load (loader, temp);temp[0] = '\0';}fclose (file);exit:cherokee_buffer_mrproper (&filename);return ret_ok;}static ret_tload_common (cherokee_plugin_loader_t *loader,     const char               *modname,     int                       flags){ret_t                   ret;entry_t                *entry     = NULL;cherokee_plugin_info_t *info      = NULL;void                   *dl_handle = NULL;/* If it is already loaded just return * 在AVL 树中查找插件名, 如果找到说明插件已经加载, 直接返回 */ret = cherokee_avl_get_ptr (&loader->table, modname, (void **)&entry);if (ret == ret_ok)return ret_ok;/* Check deps * 加载依赖的其他插件, 从文件中读取插件名然后递归调用cherokee_plugin_loader_load 加载 */ret = check_deps_file (loader, modname);if (ret != ret_ok)return ret;/* Get the module info * 加载插件对应的动态库文件, 并取得插件info 结构体 */ret = get_info (loader, modname, flags, &info, &dl_handle);switch (ret) {case ret_ok:break;case ret_error:LOG_ERROR (CHEROKEE_ERROR_PLUGIN_NO_OPEN, modname);return ret;case ret_not_found:LOG_ERROR (CHEROKEE_ERROR_PLUGIN_NO_INFO, modname);return ret;default:SHOULDNT_HAPPEN;return ret_error;}/* Add new entry * 创建新的插件实体, 设置info 和dl_handle, 插入到AVL树中 */entry = malloc (sizeof(entry_t));if (entry == NULL) {return ret_nomem;}entry->dlopen_ref = dl_handle;entry->info       = info;entry->built_in   = false;ret = cherokee_avl_add_ptr (&loader->table, modname, entry);if (unlikely(ret != ret_ok)) {dlclose (entry->dlopen_ref);free(entry);return ret;}/* Execute init function * 从 dl_handle 中读出插件初始化函数cherokee_plugin_<name>_init, 并调用 */ret = execute_init_func (loader, modname, entry);if (ret != ret_ok) {return ret;}return ret_ok;}// 取得插件结构体ret_tcherokee_plugin_loader_get (cherokee_plugin_loader_t  *loader,    const char                *modname,    cherokee_plugin_info_t   **info){ret_t ret;// 加载插件动态链接库ret = cherokee_plugin_loader_load (loader, modname);if (ret != ret_ok)return ret;// 取得结构体ret = cherokee_plugin_loader_get_info (loader, modname, info);if (ret != ret_ok)return ret;return ret_ok;}

读书人网 >开源软件

热点推荐