FS/ext2/inode. c Related Function comments

Source: Internet
Author: User

Use array chain [4] To describe four different indexes, namely direct index, first-level indirect index, second-level indirect index, and third-level indirect index. Examples illustrate the meaning of each domain in this structure. If the block number in the file is 8, no indirect index is required. Therefore, only the chain [0] is used as an indirect structure, and P points to the index table with a subscript of 8, that is, & inode-> U. ext2_ I. I _data [8]; The key holds the content of the table item, that is, the block number on the device corresponding to the file block number (similar to the relationship between the logical page number and the physical page number); BH is null because there is no block for indirect index. If the block number in the file is 20, an indirect index is required. The index must use two table items: Chian [0] and chain [1. In the first table item Chian [0], the pointer BH is still null, because this layer does not have data blocks for indirect indexing. the pointer P points to & inode-> U. ext2_ I. I _data [12] is the table item of the indirect index, and the key holds the content of the item, that is, the block number of the corresponding device. The pointer BH in chain [1] points to the buffer of the block where the indirect index is located. The content of this buffer is an integer array used as the indirect index, P points to the bottom of the array and the key holds the content of the item. In this way, according to the depth of the specific index depth, the last element in the array chain [], namely chain [depth-1]. Key, always holds the physical block number of the target data block. From the first element chain [0] In chain [] to the last element chain [depth-1] of a specific index, the entire path of a specific index is provided, it constitutes an index chain, which is also the source of the data name chain.

After learning about the above basic content, let's look at the specific implementation code of the ext2_get_block () function:

· First, call the ext2_block_to_path () function to calculate the index range of the data block based on the logic block number iblock in the file. Several indexes are required (1 indicates direct ). If the returned value is 0, an error occurs because at least one index is required between the block number in the file and the block number on the device. The cause of the error may be that the block number in the file is too large or negative.

· The ext2_get_branch () function deepens the results obtained from ext2_block_to_path (), which together basically completes the ing from the block number in the file to the block number on the device. There are two possible values returned from ext2_get_branch. First, if the ing is successfully completed, the return value is null. Second, if the corresponding table item in the index table is found to be 0 at an index level, it indicates that the data block does not exist. Now, the file size needs to be expanded due to write operations. In this case, a pointer to the indirect structure is returned, indicating that the ing is broken here. In addition, if an error occurs during the ing process, for example, if the data block reading fails, an error code is returned through err.

· If the ing is completed successfully, enter the obtained results in the buffer structure bh_result, and release all the buffers (used for indirect indexes) read during the ing process.

· However, if ext2_get_branch () returns a non-0 pointer, The ing is broken at a certain index level. Based on the depth of the ing and the location of the break, this data block may be a data block used for indirect indexing, or maybe the final data block. In any case, space should be allocated for the corresponding data block.

· To allocate space, first determine where to read the target block from the physical device. According to the allocation algorithm, the allocated data block should be stored continuously with the last allocated data block on the device. For this purpose, two I _next_alloc_block and I _next_alloc_goal fields are set in the ext2_inode_info structure. The former is used to record the block numbers in the file to be allocated next time, while the latter is used to record the block numbers on the device to be allocated next time. Under normal circumstances, the expansion of files is sequential. Therefore, the block numbers in each allocated file are sequential with those in the previous one. Ideally, the block numbers on the device are also continuous, and the two are moving forward in parallel. This ideal "Recommended block number" is found by the ext2_find_goal () function.

· The allocation of specific physical blocks on the device and the establishment of ing between data blocks in the file and physical blocks are completed by calling the ext2_alloc_branch () function. Before calling the API, you must first calculate the number of indexes that need to be created.

· After returning from ext2_alloc_branch (), we have allocated the required data blocks from the device, including the intermediate data blocks used for indirect indexing. However, the data block numbers allocated at the top of the original ing that started to be disconnected only record the key fields in its indirect structure, but are not written into the corresponding index table. Now, we need to connect the broken "branches" to the entire index tree. At the same time, we also need to make some adjustments to the relevant content in the inode structure of the file. All these operations are completed by the ext2_splice_branch () function.

So far, everything is ready. Go to got_it and place the mapped data block along with the device number in the buffer structure referred to by bh_result. This completes the allocation of data blocks.


10.1.1 what is a module

A module is a part of the kernel (usually a device driver), but it is not compiled into the kernel. They are compiled and connected to a set of target files, which can be inserted into the running kernel or removed from the running kernel, to perform these operations, you can use the insmod (insert module) or rmmod (remove module) command, or, when necessary, the kernel itself can request the kernel daemon (kerned) to mount or unload the module. Some modules included in the Linux kernel source program are listed here:

· File systems: minix, xiafs, msdos, umsdos, sysv, isofs, HPFs,

Smbfs, ext3, NFS, Proc, etc.

· Most scsi drivers: (such as aha1542 and In2000)

· All SCSI advanced Drivers: disk, tape, CDROM, and generic.

· Most Ethernet drivers: (a lot of drivers are not listed here. Please refer

./Documentation/networking/net-modules.txt)

· The majority of CD-ROM drivers:

Aztcm: AZTech, orchid, Okano, wearnes

Cm206: Philips/lms cm206

Gscd: Goldstar GCDR-420

MCD, MCX: mitsumi lu005, fx001

Optcm: Optics storage doldolphin 8000at

Sjcd: Sanyo CDR-H94A

Sbpcd: Matsushita/Panasonic cr52x, cr56x, cd200,

Longshine LCS-7260, teac CD-55A

Sonycd535: Sony CDU-531/535, CDU-510/515


· And many other modules, such:

LP: Row printer

Binfmt_elf: Elf Loader

Binfmt_java: Java Loader

Isp16: CD-ROM interface

Serial: Serial Port (TTY)

It should be noted that various file systems and device drivers in the Linux kernel can be compiled into installable modules or statically compiled into the kernel image, this depends on the user's choice in the System Configuration phase before kernel compilation. Generally, in the System Configuration phase, the system provides three options (y/M/n). "Y" indicates that a certain device or function is required, and the corresponding code is statically connected to the kernel image. "M" indicates that the code is compiled into a installable module, and "N" indicates that the device is not installed.

10.1.2 why use a module?

Dynamic Loading of modules on demand is very attractive because it can minimize the number of kernels and make the kernel very flexible. For example, if you may occasionally use the vfat file system, you only need to install (Mount) vfat and vfat file systems become a load-able module. kerneld automatically mounts the vfat file system to create your Linux kernel. When you detach the vfat part, the system detects the fat system module that you no longer need. This module is automatically removed from the kernel. Dynamic Loading of modules on demand also means that you will have more memory for your programs. As mentioned above, the memory used by the kernel will never be swapped out. Therefore, if a kb unused driver is compiled into the kernel, it means you are wasting Ram. Everything is costly. This advantage of kernel modules comes at the cost of minor performance and memory loss.

Once a Linux kernel module is loaded, it becomes a part of the kernel just like any standard kernel code. It has the same permissions and responsibilities as any kernel code. Like all kernel code or drivers, the Linux kernel module can crash the kernel.

10.1.3 Advantages and Disadvantages of Linux kernel modules

The dynamic loading of kernel modules has the following advantages:


· Keep the kernel image size to a minimum and have the maximum flexibility;
· It is easy to check new kernel code without re-compiling the kernel and re-booting.

However, the introduction of the kernel module also brings about the following problems:

· Negative impact on system performance and memory utilization;
· The mounted kernel module has the same access permissions as other kernel modules. Therefore, poor kernel modules may cause system crashes;
· To allow the kernel module to access all kernel resources, the kernel must maintain the symbol table and modify these symbol tables when loading and uninstalling modules;
· Some modules require the use of the functions of other modules. Therefore, the kernel must maintain dependencies between modules.
· The kernel must be able to notify the module when uninstalling the module and release the memory and interrupt resources allocated to the module;
· Incompatible kernel versions and module versions may also cause system crashes. Therefore, strict version checks are required.
Although the introduction of kernel modules also brings about a lot of problems, the module mechanism is indeed an effective way to expand the kernel functions and is also an effective way to program at the kernel level.


10.2.1 Data Structure
1. Module symbol

As mentioned above, the Linux kernel is an overall structure, and the module is a plug-in inserted into the kernel. Although the kernel is not a installable module, Linux regards the kernel as a module for convenience. Then, how do we interact between modules? A common method is to share variables and functions. But not every variable and function in the module can be shared. The kernel only places the main variables and functions in each module in a specific section. These variables and functions are collectively referred to as symbols. To which symbols can be shared? Linux Kernel has its own rules. For the kernel module, the "Remove" symbol is defined in kernel/ksyms. C. For example, the "Remove" symbol of the process management subsystem is defined as follows:

/* Process memory management */

Export_symbol (do_mmap_pgoff );

Export_symbol (do_munmap );

Export_symbol (do_brk );

Export_symbol (exit_mm );

Export_symbol (exit_files );

Export_symbol (exit_fs );

Export_symbol (exit_sighand );


Export_symbol (complete_and_exit );

Export_symbol (_ wake_up );

Export_symbol (_ wake_up_sync );

Export_symbol (wake_up_process );

Export_symbol (sleep_on );

Export_symbol (sleep_on_timeout );

Export_symbol (interruptible_sleep_on );

Export_symbol (interruptible_sleep_on_timeout );

Export_symbol (Schedule );

Export_symbol (schedule_timeout );

Export_symbol (jiffies );

Export_symbol (xtime );

Export_symbol (do_gettimeofday );

Export_symbol (do_settimeofday );

You may be familiar with these variables and functions. The macro defines export_symbol () as "Remove symbol ". Why is it "Remove? Because these symbols are originally symbols inside the kernel, they are put in a public place through this macro so that other modules loaded into the kernel can reference them.

In fact, it is not enough to know the names of these symbols. It is necessary to know their addresses in the kernel image. Therefore, the kernel defines the following structure to describe the module symbol:

Struct module_symbol

{

Unsigned long value;/* the address of the symbol in the kernel image */

Const char * Name;/* pointer to symbol name */

};

From the subsequent definition of the export_symbol macro, we can see that the Connection Program (LD) stores this structure in a section named "_ ksymtab" when connecting to the kernel image, all the symbols in this section form a symbol table for the module to "Remove" from the external, which can be referenced by the kernel and installed modules. Other "internal" symbols are generated by the Connection Program and used internally only.

Definitions related to export_symbol are included in include/Linux/module. h:


# DEFINE _ module_string_1 (x) # x

# DEFINE _ module_string (x) _ module_string_1 (X)


# DEFINE _ export_symbol (sym, STR )/

Const char _ kstrtab _ # sym []/

_ Attribute _ (Section (". kstrtab") = STR ;/

Const struct module_symbol _ ksymtab _ # sym/

_ Attribute _ (Section ("_ ksymtab") =/

{(Unsigned long) & sym, _ kstrtab _ # sym}


# If defined (modversions) |! Defined (config_modversions)

# Define export_symbol (VAR) _ export_symbol (VAR, _ module_string (VAR ))


The following uses export_symbol (Schedule) as an example to describe the result of this macro.

First, the export_symbol (Schedule) is defined as _ export_symbol (schedule, "Schedule "). _ Export_symbol () defines two statements. The first statement defines a string named _ kstrtab _ schedule and initializes the content of the string to schedule ", and place it in the kernel image. kstrtab section. Note that this section stores the character string. The second statement defines a module_symbol structure named _ kstrtab _ schedule and initializes it to the {& Schedule ,__ kstrtab _ schedule} structure, and place it in the _ ksymtab section of the kernel image. In this way, the value of the Domain value in the module_symbol structure is the address of schedule in the kernel image, and the pointer name points to the string "Schedule ".


2. Module reference)

Module reference is a concept that is hard to understand. Some modules loaded into the kernel must depend on other modules. For example, because the vfat file system is a more or less extended set of the FAT file system, the vfat file system depends on the FAT file system, or, the fat module is referenced by the vfat module. In other words, the vfat module is the "parent" module, and the fat module is the "sub" module. Its structure is as follows:

Struct module_ref

{

Struct module * Dep;/* "parent" module pointer */

Struct module * ref;/* "sub" module pointer */

Struct module_ref * next_ref;/* pointer to the next submodule */

};

Here, "Dep" refers to dependency, that is, reference, and "Ref" refers to being referenced. The reference relationship of a module may continue. For example, a references B and B references C. Therefore, the reference of a module forms a linked list.

3. Module

The module structure is module, which is defined as follows:

Struct module_persist;/* To be determined */


Struct module

{

Unsigned long size_of_struct;/* size of the module structure, that is, sizeof (module )*/

Struct module * Next;/* points to the next module */

Const char * Name;/* Module name, up to 64 characters */
Unsigned long size;/* Page-based module size */


Union

{

Atomic_t usecount;/* use the count to increase or decrease it by atomic operations */

Long pad;

} UC;/* needs to keep its size-So says rth */


Unsigned long flags;/* module flag */


Unsigned nsyms;/* Number of symbols in the module */

Unsigned ndeps;/* Number of module dependencies */

Struct module_symbol * Syms;/* points to the symbol table of the module. The table size is nsyms */


Struct module_ref deps;/* points to the array referenced by the module. The size is ndeps */

Struct module_ref * refs;

INT (* init) (void);/* points to the module's init_module () function */

Void (* cleanup) (void);/* points to the cleanup_module () function of the module */

Const struct prediction_table_entry * ex_table_start;

Const struct prediction_table_entry * ex_table_end;

 

/* The following domains are an extension based on the above basic domains, so they are optional. Yes

Mod_member_present () function to check whether the following fields exist. */

Const struct module_persist * persist_start;/* not defined */

Const struct module_persist * persist_end;

INT (* can_unload) (void );

Int runsize/* not used */

Const char * kallsyms_start;/* all symbols used for kernel debugging */

Const char * kallsyms_end;

Const char * archdata_start;/* specific data related to the architecture */

Const char * archdata_end;

Const char * kernel_data;/* Reserved */

};


The status in Moudle, namely, flags, is defined as follows:

/* Bits of module. Flags .*/


# Define mod_uninitialized 0/* module not initialized */

# Define mod_running 1/* the module is running */

# Define mod_deleted 2/* the process of uninstalling the module has been started */

# Define mod_autoclean 4/* indicates that automatic

Uninstall the module */

# Define mod_visited 8/* module accessed */

# Define mod_used_once 16/* The module has been used once */

# Define mod_just_freed 32/* The module has just been released */

# Define mod_initializing 64/* initializing the module */-/


As mentioned above, although the kernel is not a installable module, it also has a symbol table. In fact, these symbol tables are frequently referenced by other modules, considering the kernel as an installable module greatly simplifies the module design. Therefore, the kernel also has a module structure called kernel_module, which defines kernel_module in kernel/module_c:

# If defined (config_modules) | defined (config_kallsyms)


Extern struct module_symbol _ start ___ ksymtab [];

Extern struct module_symbol _ Stop ___ ksymtab [];


Extern const struct prediction_table_entry _ start ___ ex_table [];

Extern const struct prediction_table_entry _ Stop ___ ex_table [];


Extern const char _ start ___ kallsyms [] _ attribute _ (weak ));

Extern const char _ Stop ___ kallsyms [] _ attribute _ (weak ));


Struct module kernel_module =

{

Size_of_struct: sizeof (struct module ),

Name :"",

UC: {atomic_init (1 )},

Flags: mod_running,

Syms: _ start ___ ksymtab,

Ex_table_start: _ start ___ ex_table,

Ex_table_end: _ Stop ___ ex_table,

Kallsyms_start: _ start ___ kallsyms,

Kallsyms_end: _ Stop ___ kallsyms,

};

First, you must note that the kernel supports installable modules. If the installable module is selected in the System Configuration phase before the kernel code is compiled, the compilation prompt config_modules is defined, so that the Code supporting the installable module is compiled. Likewise, the support for symbols used for kernel debugging is optional.

All fields that do not have the preceding initial values are 0 or null. Obviously, the kernel does not have the init_module () and cleanup_module () functions, because the kernel is not a real installable module. At the same time, the kernel does not have a deps array and there is no refs chain at the beginning. However, the pointer Syms points to _ start ___ ksymtab, which is the starting address of the kernel symbol table. The size of the symbol table nsyms is 0, but it is set to a correct value in the init_module () function when the system can initialize.

The module image can also contain exception handling. Exceptions occur on some special addresses. You can use a descriptive structure exception_table_entry to reflect and handle exceptions. These structures are concentrated in an array during executable image connection, the kernel's prediction_table_entry array is _ start ___ ex_table []. When an exception occurs, the kernel's exception response handler searches for this array to see if special processing is required for the exception. For more information, see Chapter 4.

In addition, from kernel_module, the module structures of all installed modules are linked together to form a chain. The global variable module_list in the kernel points to this chain:

Struct module * module_list = & kernel_module;

Related Article

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.