Analysis of Linux driver kernel loading module process

Publisher:upsilon30Latest update time:2024-08-20 Source: cnblogs Reading articles on mobile phones Scan QR code
Read articles on your mobile phone anytime, anywhere

dst[ndst] = src[i];

//Reset the index value of the symbol name in mod->core_strtab

dst[ndst++].st_name = s - mod->core_strtab;

//Copy the symbol name to mod->module_core + info->stroffs

s += strlcpy(s, &mod->strtab[src[i].st_name],KSYM_NAME_LEN) + 1;

}

}

mod->core_num_syms = ndst; //Number of symbols

}


static int complete_formation(struct module *mod, struct load_info *info)

{

int err;


mutex_lock(&module_mutex);


// Check if there is any redefinition symbol

err = verify_export_symbols(mod);

if (err < 0)

goto out;


//Module bug related operations

module_bug_finalize(info->hdr, info->sechdrs, mod);


//Set the status of the module

mod->state = MODULE_STATE_COMING;

out:

mutex_unlock(&module_mutex);

return err;

}


static int verify_export_symbols(struct module *mod)

{

unsigned int i;

struct module *owner;

const struct kernel_symbol *s;

struct {

const struct kernel_symbol *sym;

unsigned int num;

} arr[] = {

{ mod->syms, mod->num_syms },

{ mod->gpl_syms, mod->num_gpl_syms },

{ mod->gpl_future_syms, mod->num_gpl_future_syms },

#ifdef CONFIG_UNUSED_SYMBOLS

{ mod->unused_syms, mod->num_unused_syms },

{ mod->unused_gpl_syms, mod->num_unused_gpl_syms },

#endif

};


//Traverse the symbols in the module and check in the kernel whether they have been exported. If the symbol has been exported, the famous error "exports duplicate symbol" is given.

for (i = 0; i < ARRAY_SIZE(arr); i++) {

for (s = arr[i].sym; s < arr[i].sym + arr[i].num; s++) {

if (find_symbol(s->name, &owner, NULL, true, false)) {

printk(KERN_ERR "%s: exports duplicate symbol %s"" (owned by %s)n",mod->name, s->name, module_name(owner));

return -ENOEXEC;

}

}

}

return 0;

}


static int do_init_module(struct module *mod)

{

int ret = 0;


current->flags &= ~PF_USED_ASYNC;


// Kernel notification

blocking_notifier_call_chain(&module_notify_list,MODULE_STATE_COMING, mod);


//Set RO and NX regions for core

set_section_ro_nx(mod->module_core,mod->core_text_size,mod->core_ro_size,mod->core_size);


//Set RO and NX regions for init

set_section_ro_nx(mod->module_init,mod->init_text_size,mod->init_ro_size,mod->init_size);


//Call the module constructor

do_mod_ctors(mod);


//Start the module

if (mod->init != NULL)

ret = do_one_initcall(mod->init);


if (ret < 0) {

/* Init routine failed: abort. Try to protect us from buggy refcounters. */

mod->state = MODULE_STATE_GOING;

synchronize_sched();

module_put(mod);

blocking_notifier_call_chain(&module_notify_list,MODULE_STATE_GOING, mod);

free_module(mod);

wake_up_all(&module_wq);

return ret;

}

if (ret > 0) {

printk(KERN_WARNING"%s: '%s'->init suspiciously returned %d, it should follow 0/-E conventionn""%s: loading module anyway...n",__func__,mod->name, ret, __func__);

dump_stack();

}


//Module initialization completed, change status, notify the kernel

mod->state = MODULE_STATE_LIVE;

blocking_notifier_call_chain(&module_notify_list,MODULE_STATE_LIVE, mod);


if (current->flags & PF_USED_ASYNC)

async_synchronize_full();

mutex_lock(&module_mutex);

/* Drop initial reference. */

module_put(mod);

rim_init_extable(mod);

#ifdef CONFIG_KALLSYMS

mod->num_symtab = mod->core_num_syms;

mod->symtab = mod->core_symtab;

mod->strtab = mod->core_strtab;

#endif

//Release the initialization space, which is only valid during initialization. After initialization, recycle resources and clear

unset_module_init_ro_nx(mod);

module_free(mod, mod->module_init);

mod->module_init = NULL;

mod->init_size = 0;

mod->init_ro_size = 0;

mod->init_text_size = 0;

mutex_unlock(&module_mutex);

wake_up_all(&module_wq);

return 0;

}


int __init_or_module do_one_initcall(initcall_t fn)

{

int count = preempt_count();

int ret;

char msgbuf[64];


if (initcall_debug)

ret = do_one_initcall_debug(fn);

else

ret = fn(); //Execute the init_module function of the module


msgbuf[0] = 0;


if (preempt_count() != count) {

sprintf(msgbuf, "preemption imbalance ");

preempt_count() = count;

}


if (irqs_disabled()) {

strlcat(msgbuf, "disabled interrupts ", sizeof(msgbuf));

local_irq_enable();

}

WARN(msgbuf[0], "initcall %pF returned with %sn", fn, msgbuf);


return ret;

}


[1] [2] [3] [4] [5] [6] [7] [8]
Reference address:Analysis of Linux driver kernel loading module process

Previous article:Linux driver to create a hello module
Next article:S3C2440 Watchdog Timer Principle

Recommended ReadingLatest update time:2024-11-16 20:32

Linux driver: s3c2410_ts/s3c2440_ts module loading process
Preface By analyzing the s3c2410_ts/s3c2440_ts module loading process, the bus-device-driver model and input subsystem framework in the Linux driver are analyzed . Main process analysis diagram s3c2440_ts main process analysis system initialization MACHINE_START(SMDK2410,"SMDK2410") MACHINE_START(SMDK2410, "SMDK241
[Microcontroller]
[Linux bottom layer] U-boot ksz8081 network driver debugging
Micrel is an excellent PHY chip. For more information about the chip, please refer to: ksz8081 datasheet interpretation System version: Ubuntu18.04-64 Compiler version: gcc version 7.4.0 (Ubuntu/Linaro 7.4.0-1ubuntu1~18.04.1) uboot version: 2018.07-linux4sam_6.0 Board model: at91sama5d3x-xplained MCU mode
[Microcontroller]
LCD device driver in Linux (1) - framebuffer
1. framebuffer Framebuffer is an interface provided by Linux system for display devices. It abstracts the display buffer, shields the underlying differences of image hardware, and allows upper-level applications to directly read and write the display buffer in graphics mode. Users do not need to care about the speci
[Microcontroller]
LCD device driver in Linux (1) - framebuffer
09-S3C2440 driver learning (Part 3) Embedded Linux platform bus driver and separation and layering driver framework
Introduction Platform: The kernel has IIC bus, PCI bus, serial bus, SPI bus, CAN bus, single bus, etc. Some devices can be mounted on these buses, and then the devices and drivers are matched through bus matching. However, some devices do not belong to these buses, so a virtual bus, that is, Platform bus, is introdu
[Microcontroller]
09-S3C2440 driver learning (Part 3) Embedded Linux platform bus driver and separation and layering driver framework
S3C6410 RTC driver in Linux (3)
The previous article talked about the s3c_rtc_probe function, but because it was too long, I didn’t finish it. This article continues the previous article. After talking about this function, we can go back to the s3c_rtc_probe function and continue talking about it in the next article. Do you still remember this sen
[Microcontroller]
S3C6410 RTC driver in Linux (3)
S3C2416 Linux2.6.21 driver porting - added UART3 and baud rate setting bug eliminated
1. Transplantation Environment (The red bold text indicates the modified content, and the blue bold text indicates the content with special attention) 1.Host environment: Ubuntu-10.10 under Virtualbox 2. Compilation Compilation environment: arm-linux-gcc v4.4.3 3.uboot: U-Boot 1.3.4 (provided by Youjian) 4. Li
[Microcontroller]
Latest Microcontroller Articles
  • Download from the Internet--ARM Getting Started Notes
    A brief introduction: From today on, the ARM notebook of the rookie is open, and it can be regarded as a place to store these notes. Why publish it? Maybe you are interested in it. In fact, the reason for these notes is ...
  • Learn ARM development(22)
    Turning off and on interrupts Interrupts are an efficient dialogue mechanism, but sometimes you don't want to interrupt the program while it is running. For example, when you are printing something, the program suddenly interrupts and another ...
  • Learn ARM development(21)
    First, declare the task pointer, because it will be used later. Task pointer volatile TASK_TCB* volatile g_pCurrentTask = NULL;volatile TASK_TCB* vol ...
  • Learn ARM development(20)
    With the previous Tick interrupt, the basic task switching conditions are ready. However, this "easterly" is also difficult to understand. Only through continuous practice can we understand it. ...
  • Learn ARM development(19)
    After many days of hard work, I finally got the interrupt working. But in order to allow RTOS to use timer interrupts, what kind of interrupts can be implemented in S3C44B0? There are two methods in S3C44B0. ...
  • Learn ARM development(14)
  • Learn ARM development(15)
  • Learn ARM development(16)
  • Learn ARM development(17)
Change More Related Popular Components

EEWorld
subscription
account

EEWorld
service
account

Automotive
development
circle

About Us Customer Service Contact Information Datasheet Sitemap LatestNews


Room 1530, 15th Floor, Building B, No.18 Zhongguancun Street, Haidian District, Beijing, Postal Code: 100190 China Telephone: 008610 8235 0740

Copyright © 2005-2024 EEWORLD.com.cn, Inc. All rights reserved 京ICP证060456号 京ICP备10001474号-1 电信业务审批[2006]字第258号函 京公网安备 11010802033920号