void native_procedure_init() {
TABLE_LIST tables;
MEM_ROOT mem;
READ_RECORD read_record_info;
TABLE *table;
int error;
DBUG_ENTER("native_procedure_init");
#ifdef HAVE_PSI_INTERFACE
init_psi_keys();
#endif
mysql_rwlock_init(key_THR_LOCK_np, &THR_LOCK_np);
init_sql_alloc(&mem, UDF_ALLOC_BLOCK_SIZE, 0);
// Initialize THD (we don't have THD during server startup).
THD *new_thd = new THD;
if (!new_thd) {
// NO_LINT_DEBUG
sql_print_error("Can't allocate memory for native procedures");
free_root(&mem, MYF(0));
DBUG_VOID_RETURN;
}
new_thd->thread_stack = (char *)&new_thd;
new_thd->store_globals();
new_thd->set_db(system_db, sizeof(system_db) - 1);
// Open mysql.native_proc table.
tables.init_one_table(system_db, sizeof(system_db), system_table,
sizeof(system_table), system_table, TL_READ);
if (open_and_lock_tables(new_thd, &tables, FALSE,
MYSQL_LOCK_IGNORE_TIMEOUT)) {
// NO_LINT_DEBUG
sql_print_error("Can't open the mysql.native_proc table. "
"Please run mysql_upgrade to create it.");
goto exit;
}
// Read records in table.
table = tables.table;
if (init_read_record(&read_record_info, new_thd, table, NULL, 1, 1, FALSE))
goto exit;
table->use_all_columns();
while (!(error = read_record_info.read_record(&read_record_info))) {
native_proc np;
np.name = get_field(&mem, table->field[0]);
np.dl = get_field(&mem, table->field[2]);
DBUG_ASSERT(strcmp("native", get_field(&mem, table->field[1])) == 0);
if (add_native_procedure(&np)) {
// NO_LINT_DEBUG
sql_print_error("Error adding native procedure: '%.64s'",
np.name.c_str());
} else {
DBUG_ASSERT(proc_map.count(np.name) > 0);
proc_map[np.name].enabled = true;
}
}
if (error > 0) {
// NO_LINT_DEBUG
sql_print_error("Got unknown error: %d", my_errno);
}
end_read_record(&read_record_info);
// Force close to free memory.
table->m_needs_reopen = TRUE;
exit:
close_mysql_tables(new_thd);
free_root(&mem, MYF(0));
delete new_thd;
my_pthread_setspecific_ptr(THR_THD, 0);
DBUG_VOID_RETURN;
}
看源码 它是先从 system_table 中找相关符号 然后读取,之后做 add_native_procedure
static int add_native_procedure(native_proc *np) {
void *dl = nullptr;
bool dlclose_needed = false;
if (proc_map.count(np->name) > 0) {
my_error(ER_NP_PROCEDURE_EXISTS, MYF(0), np->name.c_str());
return 1;
}
dl = search_dlhandle(np->dl);
// If dlhandle not present, dlopen the shared object.
if (dl == nullptr) {
char dlpath[FN_REFLEN];
strxnmov(dlpath, sizeof(dlpath) - 1, opt_plugin_dir, "/", np->dl.c_str(),
NullS);
unpack_filename(dlpath, dlpath);
if (!(dl = dlopen(dlpath, RTLD_NOW))) {
const char *errmsg;
int error_number = dlopen_errno;
DLERROR_GENERATE(errmsg, error_number);
my_error(ER_CANT_OPEN_LIBRARY, MYF(0), np->dl.c_str(), error_number,
errmsg);
return 1;
}
dlclose_needed = true;
}
np->dlhandle = dl;
// Lookup function pointer with dlsym.
if (!(np->proc = (proc_t *)dlsym(np->dlhandle, np->name.c_str()))) {
my_error(ER_CANT_FIND_DL_ENTRY, MYF(0), np->name.c_str());
if (dlclose_needed) {
DBUG_ASSERT(dl);
dlclose(dl);
}
return 1;
}
// Insert into proc_map.
proc_map[np->name] = *np;
return 0;
}
这里做了将 名字 和 函数做了关联 分别用了 dlopen(打开句柄),dlsym符号链接