The Linux kernel supports dynamic loading of modules: for example, insmod first_drv.ko, so that the module can be loaded into the kernel space for application calls. Now briefly describe the process of insmod first_drv.ko
1. insmod is also a user process
2. The insmod process reads the name of the module to be linked from the command line: first_drv.ko
3. The insmod process determines the location of the file where the module object code is located in the system directory tree, that is, the location of the first_drv.ko file
4. The insmod process reads the file containing the module target code from the storage area where the file system is located
5. insmod calls the init_module system call. The function will enter the kernel to reach the kernel function sys_init_module, and then the sys_init_module function will copy the module binary file to the kernel, and then the kernel will complete the rest of the tasks.
The following content is reproduced from https://blog.csdn.net/chrovery/article/details/51088425
1. Introduction
When some modules compiled now are insmoded on the system, various errors may be reported. The causes of these errors can be found by carefully reading the kernel source code. The insmod part of the 2.6 kernel and before mainly relied on the modutils source code package, and basically completed the work at the user level. The loading process is referred to the previous article. The practice after the 2.6 kernel is to incorporate most of the original user-level operations into the kernel for processing, which is much less than before in terms of logic and code volume. It is connected to the kernel through the insmod command in busybox. If you understand this set of source code, you will not encounter various errors when loading modules. You can write some patch code to correct the items that the kernel needs to check, such as vermagic and crc, etc.
2. Related Structure
1. Module Dependencies
struct module_use {
struct list_head source_list;
struct list_head target_list;
struct module *source, *target;
};
2. Module status
enum module_state {
MODULE_STATE_LIVE, /* Normal state. */
MODULE_STATE_COMING, /* Full formed, running module_init. */
MODULE_STATE_GOING, /* Going away. */
MODULE_STATE_UNFORMED, /* Still setting it up. */
};
3. Module Count
struct module_ref {
unsigned long incs;
unsigned long decs;
} __attribute((aligned(2 * sizeof(unsigned long))));
4. Module Structure
struct module
{
enum module_state state;
/* Member of list of modules */
struct list_head list;
/* Unique handle for this module */
char name[MODULE_NAME_LEN];
/* Sysfs stuff. */
struct module_kobject mkobj;
struct module_attribute *modinfo_attrs;
const char *version;
const char *srcversion;
struct kobject *holders_dir;
/* Exported symbols */
const struct kernel_symbol *syms;
const unsigned long *crcs;
unsigned int num_syms;
/* Kernel parameters. */
struct kernel_param *kp;
unsigned int num_kp;
/* GPL-only exported symbols. */
unsigned int num_gpl_syms;
const struct kernel_symbol *gpl_syms;
const unsigned long *gpl_crcs;
#ifdef CONFIG_UNUSED_SYMBOLS
/* unused exported symbols. */
const struct kernel_symbol *unused_syms;
const unsigned long *unused_crcs;
unsigned int num_unused_syms;
/* GPL-only, unused exported symbols. */
unsigned int num_unused_gpl_syms;
const struct kernel_symbol *unused_gpl_syms;
const unsigned long *unused_gpl_crcs;
#endif
#ifdef CONFIG_MODULE_SIG
/* Signature was verified. */
bool sig_ok;
#endif
/* symbols that will be GPL-only in the near future. */
const struct kernel_symbol *gpl_future_syms;
const unsigned long *gpl_future_crcs;
unsigned int num_gpl_future_syms;
/* Exception table */
unsigned int num_exentries;
struct exception_table_entry *extable;
/* Startup function. */
int (*init)(void);
/* If this is non-NULL, vfree after init() returns */
void *module_init;
/* Here is the actual code + data, vfree'd on unload. */
void *module_core;
/* Here are the sizes of the init and core sections */
unsigned int init_size, core_size;
/* The size of the executable code in each section. */
unsigned int init_text_size, core_text_size;
/* Size of RO sections of the module (text+rodata) */
unsigned int init_ro_size, core_ro_size;
/* Arch-specific module values */
struct mod_arch_specific arch;
unsigned int taints; /* same bits as kernel:tainted */
#ifdef CONFIG_GENERIC_BUG
/* Support for BUG */
unsigned num_bugs;
struct list_head bug_list;
struct bug_entry *bug_table;
#endif
#ifdef CONFIG_KALLSYMS
Elf_Sym *symtab, *core_symtab;
unsigned int num_symtab, core_num_syms;
char *strtab, *core_strtab;
/* Section attributes */
struct module_sect_attrs *sect_attrs;
/* Note attributes */
struct module_notes_attrs *notes_attrs;
#endif
char *args;
#ifdef CONFIG_SMP
/* Per-cpu data. */
void __percpu *percpu;
unsigned int percpu_size;
#endif
#ifdef CONFIG_TRACEPOINTS
unsigned int num_tracepoints;
struct tracepoint * const *tracepoints_ptrs;
#endif
#ifdef HAVE_JUMP_LABEL
struct jump_entry *jump_entries;
unsigned int num_jump_entries;
#endif
#ifdef CONFIG_TRACING
unsigned int num_trace_bprintk_fmt;
const char **trace_bprintk_fmt_start;
#endif
#ifdef CONFIG_EVENT_TRACING
struct ftrace_event_call **trace_events;
unsigned int num_trace_events;
#endif
#ifdef CONFIG_FTRACE_MCOUNT_RECORD
unsigned int num_ftrace_callsites;
unsigned long *ftrace_callsites;
#endif
#ifdef CONFIG_MODULE_UNLOAD
/* What modules depend on me? */
struct list_head source_list;
/* What modules do I depend on? */
struct list_head target_list;
/* Who is waiting for us to be unloaded */
struct task_struct *waiter;
/* Destruction function. */
void (*exit)(void);
struct module_ref __percpu *refptr;
#endif
#ifdef CONFIG_CONSTRUCTORS
/* Constructor functions. */
ctor_fn_t *ctors;
unsigned int num_ctors;
#endif
};
5. ELF file information structure
struct load_info {
Elf_Ehdr *hdr; //point to the elf header
unsigned long len;
Elf_Shdr *sechdrs; //point to the section header
char *secstrings; //Points to the address of the section name in the string section
char *strtab; //points to the address of the string section
unsigned long symoffs;
unsigned long stroffs;
struct _ddebug *debug;
unsigned int num_debug;
bool sig_ok; //Module signature check
struct {
unsigned int sym; //module symbol table section index number
unsigned int str; //Module string section index number
unsigned int mod; //module's ".gnu.linkonce.this_module" section index number
unsigned int vers; //module's "__versions" section index
unsigned int info; //module's .modinfo section index number
unsigned int pcpu;
} index;
};
3. Source code analysis
//In the insmod.c file in busybox
int insmod_main(int argc UNUSED_PARAM, char **argv)
{
char *filename;
int rc;
IF_FEATURE_2_4_MODULES(
getopt32(argv, INSMOD_OPTS INSMOD_ARGS);
argv += optind - 1;
);
//Get the path name of the module to be loaded
filename = *++argv;
if (!filename)
bb_show_usage();
rc = bb_init_module(filename, parse_cmdline_module_options(argv,0));
if (rc)
bb_error_msg("can't insert '%s': %s", filename, moderror(rc));
return rc;
}
char* FAST_FUNC parse_cmdline_module_options(char **argv, int quote_spaces)
{
char *options;
int optlen;
options = xzalloc(1);
optlen = 0;
//Traverse the module parameters after the module name
while (*++argv) {
const char *fmt;
const char *var;
const char *val;
var = *argv;
// Allocate space for options
options = xrealloc(options, optlen + 2 + strlen(var) + 2);
fmt = "%.*s%s";
//If '=' exists in var, then return the pointer to the first position where '=' appears in var, otherwise return the null character at the end of the string var.
val = strchrnul(var, '=');
if (quote_spaces) {//is 0
if (*val) { /* has var=val format. skip '=' */
val++;
if (strchr(val, ' '))
fmt = "%.*s"%s" ";
}
}
// The module parameters are stored in options in the format of "%.*s%s". "*" corresponds to (int)(val - var), and the first s corresponds to var, which means that (int)(val - var) characters are removed from the var string, that is, the characters before = are removed. In fact, only the val string (that is, the string after =) is stored in the address pointed to by the options pointer.
optlen += sprintf(options + optlen, fmt, (int)(val - var), var, val);
}
return options;
}
int FAST_FUNC bb_init_module(const char *filename, const char *options)
{
size_t image_size;
char *image;
int rc;
bool mmaped;
if (!options)
options = "";
//If the version before 2.6 calls bb_init_module_24(), this process is the module loading process of modutils in the past. Here we will study the module loading process after 2.6
#if ENABLE_FEATURE_2_4_MODULES
if (get_linux_version_code() < KERNEL_VERSION(2,6,0))
return bb_init_module_24(filename, options);
#endif
image_size = INT_MAX - 4095; //Initialize to the maximum value of the file
mmaped = 0;
//Map the module file into memory and return the size of the mapped space image_size
image = try_to_mmap_module(filename, &image_size);
if (image) {
mmaped = 1;
} else {
errno = ENOMEM; /* may be changed by eg open errors below */
image = xmalloc_open_zipped_read_close(filename, &image_size);
if (!image)
return -errno;
}
errno = 0;
Previous article:Linux driver to create a hello module
Next article:S3C2440 Watchdog Timer Principle
Recommended ReadingLatest update time:2024-11-16 18:00
Professor at Beihang University, dedicated to promoting microcontrollers and embedded systems for over 20 years.
- Innolux's intelligent steer-by-wire solution makes cars smarter and safer
- 8051 MCU - Parity Check
- How to efficiently balance the sensitivity of tactile sensing interfaces
- What should I do if the servo motor shakes? What causes the servo motor to shake quickly?
- 【Brushless Motor】Analysis of three-phase BLDC motor and sharing of two popular development boards
- Midea Industrial Technology's subsidiaries Clou Electronics and Hekang New Energy jointly appeared at the Munich Battery Energy Storage Exhibition and Solar Energy Exhibition
- Guoxin Sichen | Application of ferroelectric memory PB85RS2MC in power battery management, with a capacity of 2M
- Analysis of common faults of frequency converter
- In a head-on competition with Qualcomm, what kind of cockpit products has Intel come up with?
- Dalian Rongke's all-vanadium liquid flow battery energy storage equipment industrialization project has entered the sprint stage before production
- Allegro MicroSystems Introduces Advanced Magnetic and Inductive Position Sensing Solutions at Electronica 2024
- Car key in the left hand, liveness detection radar in the right hand, UWB is imperative for cars!
- After a decade of rapid development, domestic CIS has entered the market
- Aegis Dagger Battery + Thor EM-i Super Hybrid, Geely New Energy has thrown out two "king bombs"
- A brief discussion on functional safety - fault, error, and failure
- In the smart car 2.0 cycle, these core industry chains are facing major opportunities!
- The United States and Japan are developing new batteries. CATL faces challenges? How should China's new energy battery industry respond?
- Murata launches high-precision 6-axis inertial sensor for automobiles
- Ford patents pre-charge alarm to help save costs and respond to emergencies
- New real-time microcontroller system from Texas Instruments enables smarter processing in automotive and industrial applications
- My uploaded data
- Free application for new products: Arteli Value Edition, M4 core AT32F421 board
- Is the era of 5G small base stations about to begin?
- Contest entries submitted to Environmental Monitoring Terminal
- STM32 driver MAX7219 failed, help
- Research and implementation of median filter algorithm for license plate recognition based on FPGA.pdf
- Electrolytic Capacitors
- 【2022 Digi-Key Innovation Design Competition】Font Application in U8g2
- I want to buy a power supply. Does anyone have any recommendations?
- SinlinxA33 SD card programming