__init, __initdata and other attribute flags, the code to put this attribute into the .init.text section of the target file, the data into the .init.data section - this process is provided by the relevant target platform when compiling the kernel The xxx.lds link script guides ld to complete.
For code and data compiled into a module, the function of the __init attribute is executed when the module is loaded;
For code and data that is statically programmed into the kernel, when the kernel boots, the do_basic_setup() function calls the do_initcalls() function, which is responsible for the execution of all .init section functions.
After the initialization is complete, the memory occupied by the function or data identified by these keywords will be released.
1) All functions marked as __init are placed in the section .init.text at the time of linking. "__init" only tells the kernel. This function is only used during the initialization phase. The memory resources used after use are released.
In this section, the order in which the functions are placed is related to the order of the links and is undefined. 2) All __init functions also store a function pointer in the section .initcall.init. At initialization, the kernel will call these __init function pointers through these function pointers, and release the entire init area after the entire initialization is completed. Segments (including .init.text, .initcall.init, etc.), note that the order in which these functions are called during kernel initialization is only related to the order of the function pointers here, and the functions described in 1) are themselves in .init The order in the .text section is irrelevant. In the 2.4 kernel, the order of these function pointers is also related to the order of the links, which is undefined. In the 2.6 kernel, the initcall.init section is divided into 7 subsections, which are
.initcall1.init .initcall2.init .initcall3.init .initcall4.init .initcall5.init .initcall6.init .initcall7.init
(See include/linux/init.h and vmlinux.lds.) When you need to put the function fn in the .initcall1.init section, just declare core_initcall(fn); The other methods for defining each section are:
Core_initcall(fn) --->.initcall1.init postcore_initcall(fn) --->.initcall2.init arch_initcall(fn) --->.initcall3.init subsys_initcall(fn) --->.initcall4.init fs_initcall( Fn) --->.initcall5.init device_initcall(fn) --->.initcall6.init late_initcall(fn) --->.initcall7.init
The 2.4-compatible initcall(fn) is equivalent to device_initcall(fn). The order between the sub-sections is determined by first calling the function pointer in .initcall1.init and then calling the function pointer in .initcall2.init, and so on. The order of the function pointers in each subsection is related to the order of the links and is undefined. In the kernel, different init functions are placed in different sub-sections, thus determining the order in which they are called. This also solves the problem that some init functions must guarantee a certain order of invocation.
2. Important macro definitions related to segments in Linux Kernel source code
A. About __init, __initdata, __exit, __exitdata, and similar macros
Open the file in the Linux Kernel source tree: include / init.h, you can see the following macro decision:
#define __init __attribute__ ((__section__ (".init.text"))) __cold
#define __initdata __attribute__ (( __section__ (".init.data")))
#define __exitdata __attribute__ (( __section__ (".exit.data")))
#define __exit_call __attribute_used__ __attribute__ (( __section__ (".exitcall.exit")))
#define __init_refok oninline __attribute__ ((__section__ (".text.init.refok")))
#define __initdata_refok __attribute__ ((__section__ (".data.init.refok")))
#define __exit_refok noinline __attribute__ ((__section__ (".exit.text.refok")))
.........
#ifdef MODULE
#define __exit __attribute__ (( __section__ (".exit.text"))) __cold
#else
#define __exit __attribute_used__ __attribute__ ((__section__ (".exit.text"))) __cold
#endif
For those who often write driver modules or look through the Kernel source code, see the familiar macros: __init, __initdata, __exit, __exitdata.
The most common place for the __init macro is the definition of the driver module initialization function. The purpose is to put the initialization function of the driver module into the input section called .init.text. When the kernel is booted, the memory in this section will be freed for other uses.
The __initdata macro is used for data definitions to put data into an input section called .init.data. Several other macros are similar.
It should also be noted that in the above definition, the section is replaced by __section__. There are other similar macro definitions, which are not listed here, and their roles are similar.
Module loading is divided into dynamic loading and static loading.
The so-called static loading is to load the module when booting the system, which is compiled into the kernel.
Dynamic loading is to load the module after booting, which is compiled into a module!
Init_module is the default module entry. If you want to specify other functions as the module's entry, you need the module_init function to specify it.
Module_init (your_func);
Where your_func is the name of a function you wrote.
Init_module() is the real entry, and module_init is a macro. If used in a module, it will eventually be converted to init_module().
If not used in a module, module_init can be said to have no effect. In short, use module_init to facilitate code porting between modules and non-modules.
Small computer system interface (SCSI) is an independent processor standard for system level interfaces between computers and intelligent devices (hard disks, floppy drives, optical drives, printers, scanners, etc.). SCSI is an intelligent universal interface standard.
The last SCSI device in the SCSI chain uses a terminator, and the intermediate device does not need a terminator. Once the terminator is used by the intermediate device, the SCSI card cannot find the future SCSI device. If the last device does not use a terminator, SCSI will not work properly. Terminator is composed of resistors, located at the end of the SCSI bus, to reduce the mutual influence of the signal, maintain the constant voltage on the SCSI chain.
Most of the SCSI devices have built-in terminators and use a jumper to control on / off. The SCSI device is highly intelligent and can automatically control the terminator on / off. For example, if a hard disk is connected to a CD-ROM, the CD-ROM can work normally regardless of whether the terminator of the hard disk is on or off. However, when two hard disks are connected, the situation becomes more complicated. Before two Seagate hard disks are connected, one hard disk terminator must be off. Before a Seagate hard disk is connected to a quantum hard disk, a hard disk terminator can work normally regardless of whether it is on or off.
SCSI-90°DIP Section
ShenZhen Antenk Electronics Co,Ltd , https://www.antenkconn.com