With the widespread use of the Linux operating system, in particular the development of Linux in the embedded field, more and more people began to devote them into Linux kernels. In the face of increasingly huge Linux kernel source code, the developer will face the same problem after completing its own kernel code, that is, how to integrate the source code into the Linux kernel, increase the corresponding Linux configuration option, and finally compiled Enter the Linux kernel. This requires understanding Linux's kernel configuration system.
As we all know, the Linux kernel is developed by Linux enthusiasts distributed around the world, and Linux core is facing many new changes every day. However, the organization of the Linux kernel does not have a chaotic phenomenon, but it looks very concise, and has good scalability, developers can easily add new content to the Linux core. One of the reasons is that Linux uses a modular kernel configuration system to ensure the scalability of the kernel.
This article first analyzes the configuration system structure in the Linux kernel, and then explains the format of the makefile and configuration file, and the meaning of the configuration statement. Finally, through a simple example - Test Driver, how to add the code that will be developed Linux kernel. In the following article, it is impossible to explain all the features and commands, only explain those commonly used, as for those who are not discussed, please refer to the references later.
1. Configuring the basic structure of the system
The Linux kernel configuration system consists of three parts, namely:
Makefile: Distributed Makefile in Linux kernel source, defines the compilation rules for Linux kernels; configuration files (config.in): Provide users with configuration selection; configuration tools: including configuration command interpreter (used in configuration scripts) The configuration command is interpreted) and configure the user interface (providing the character interface, the NCurses graphical interface, and the User configuration interface based on the XWINDOWS graphics interface, each corresponds to make config, make menuconfig and make xconfig.
These configuration tools are written using scripting languages, such as TCL / TK, and PERL (also containing some code written with C). This article is not analyzing the configuration system itself, but is described on how to use the configuration system. Therefore, unless the maintenance of the system is configured, the general kernel developers do not need to understand their principles, just know how to write Makefile and configuration files. So, in this article, we only discuss the Makefile and configuration files. In addition, anything related to the specific CPU architecture is involved in ARM as an example, which can not only be explicitly discussed, but also affect the content itself.
2. Makefile
2.1 Makefile Overview
The role of makefile is based on the configuration, constructs a list of source files that need to be compiled, and then compile, and then connect the target code link together, and finally forms the Linux kernel binary file.
Since the Linux kernel source code is organized according to the tree structure, Makefile is also distributed in the directory tree. Makefile in the Linux kernel and the documents directly related to Makefile are:
Makefile: The top Makefile is the overall control file for the entire kernel configuration and compiled. .config: The kernel profile contains the configuration options selected by the user to store the results after the kernel configuration (such as make config). Arch / * / makefile: Makefile under various CPU systems, such as Arch / ARM / Makefile, is a Makefile for a specific platform. Makefile under each child: such as Drivers / Makefile, is responsible for the management of the subscription of the subdirectory. Rules.make: Rules files are used by all makefile. After the user is configured by make config, it creates .config. The top layer makefile reads the configuration selection in .config. Top Makefile has two main tasks: generating a VMLinux file and kernel module. In order to achieve this, the top Makefile recursive into each subdirectory of the kernel, which calls the Makefile located in these subdirectories, respectively. As for which subdirectories in the end, depending on the configuration of the kernel. In the top Makefile, there is a saying: including include Arch / $ (Arch) / makefile, contains Makefile under a specific CPU architecture, which contains platform-related information in this makefile.
Makefile located in each sub-directory also constructs a list of source files required under current configuration according to the configuration information given by .config, and has the last included files / Rules.make.
Rules.make files play a very important role in which all Makefile shared compilation rules. For example, if you need to compile all the C programs in this directory into assembly code, you need to have the following compilation rules in Makefile:
% .s:% .c
$ (Cc) $ (cflags) -s $ <-o $ @
There are also many subdirectories, which will need this compilation rules in their respective makefiles. This will be more troublesome. In the Linux kernel, set such compilation rules to Rules.make and include Rules.make (include Rules.make) in their respective makefiles, which avoids the same thing in multiple Makefile. rule. For the above example, the rules corresponding in Rules.make are:
% .s:% .c
$ (Cc) $ (cflags) $ (cflags _ $ (* f)) $ (cflags _ $ @) - $ <-o $ @
2.2 Variables in Makefile
Top Makefile definitions and outputs many variables to the environment to pass some information for Makefile under each child. Some variables, such as Subdirs, not only defined in the top Makefile, but also expanded in Arch / * / Makefile.
Common variables have the following categories:
1) Version information version information is: Version, PatchLevel, SUBLVEL, Extraversion, Kernelrelease. The version information defines the current core version, such as Version = 2, PatchLevel = 4, SUBLEVEL = 18, ExataVersion = -rmk7, which constitutes a library of kernel release kernelrelease: 2.4.18-RMK72) CPU architecture: Arch on the top Makefile The beginning, define the architecture of the target CPU with Arch, such as Arch: = ARM, etc. In Makefile of many subdirectories, select the list of selected source files based on the definition of Arch.
3) Path Information: TOPDIR, SUBDIRSTOPDIR Defines the root directory where Linux kernel source code is located. For example, Makefile under each child can find the location of Rules.make through $ (TOPDIR) /Rules.make. Subdirs defines a list of directory. When compiling kernel or modules, the top Makefile is based on SubDirs to decide which subdirectory. The value of SubDirs depends on the configuration of the kernel. The SubDirs in the top Makefile assigns Kernel Drivers MM FS Net IPC lib. According to the configuration of the kernel, the example in which SubDirs is expanded in the Arch / * / Makefile, see 4).
4) Nuclear composition information: Head, core_files, networks, drivers, libslinux kernel file VMLinux is generated by the following rules:
VMLinux: $ (Configuration) init / main.o init / version.o linuxsubdirs
$ (LD) $ (LINKFLAGS) $ (head) init / main.o init / version.o /
--Start-Group /
$ (More_files) /
$ (Drivers) /
$ (NetWorks) /
$ (LIBS) /
--end-group /
-o vmlinux
It can be seen that VMLinux consists of Head, Main.o, Version.o, Core_Files, Drivers, Networks, and Libs. These variables (such as HEAD) are used to define a list of target files and library files that generate VMLinux. Among them, Head is defined in Arch / * / Makefile to determine the list of files that are first link to VMLinux. For example, for the ARM series CPU, Head is defined as:
HEAD: = Arch / ARM / KERNEL / HEAD - $ (Processor) .o /
Arch / arm / kernel / init_task.o
Indicates that HEAD - $ (Processor) .o and init_task.o need to be first linked to VMLinux. Processor is ARMV or ARMO, depending on the target CPU. Core_files, network, drivers, and libs are defined in the top Makefile and expanded as needed by Arch / * / Makefile. Core_files corresponds to the core file of the kernel, with kernel / kernel.o, mm / mm.o, fs / fs.o, IPC / IPC.O, which can be seen that these are the most important files that make up the kernel. At the same time, Arch / ARM / Makefile expands to Core_Files: # Arch / ARM / Makefile
# Ration..................
Machdir: = Arch / ARM / Mach - $ (Machine)
IFEQ ($ (Machdir), $ (Wildcard $ (Machdir))
SubDirs = $ (Machdir)
Core_files: = $ (Machdir) / $ (Machine) .o $ (Core_Files)
ENDIF
HEAD: = Arch / ARM / KERNEL / HEAD - $ (Processor) .o /
Arch / arm / kernel / init_task.o
Subdirs = Arch / ARM / KERNEL ARCH / ARM / MM ARCH / ARM / LIB ARCH / ARM / NWFPE
Core_files: = Arch / ARM / KERNEL / KERNEL.O ARCH / ARM / MM / MM.O $ (Core_Files)
Libs: = Arch / ARM / LIB / LIB.A $ (LIBS)
5) Compilation Information: CPP, CC, AS, LD, AR, CFLAGS, LINKFLAGS defined in Rules.make, is defined in compilation, specific to specific occasions, need to explicitly give the compilation environment, the compilation environment is above Defined in variables. CROSS_COMPILE is defined for cross-compilation requirements. such as:
Cross_compile = arm-linux-
CC = $ (Cross_Compile) GCC
LD = $ (Cross_Compile) LD
......
Cross_compile defines the cross-compiler prefix ARM-Linux-, indicating that all cross-compilation tools are starting with ARM-Linux, so they have added $ (cross_compile) before each cross-compiler tool to make up a complete Cross-compilation tool file name, such as ARM-Linux-GCC. CFLAGS defines the parameters passing to the C compiler. LinkFlags is the parameter used by the linker when the link generates VMLinUX. LinkFlags is defined in ARM / * / Makefile, such as:
# Arch / ARM / Makefile
LinkFlags: = - p-x -t arch / arm / vmlinux.lds
6) Configure the variable config _ *. There are many configuration variables in the config file to explain the results of the user configuration. For example, Config_Modules = Y indicates that the user selects the module function of the Linux kernel. After the .config is included, a number of configuration variables are formed, each configuration variable has a determined value: Y indicates that the core code corresponding to the compilation option is static to the Linux kernel; M represents the core code corresponding to the compilation option Compiled into a module; n means that you don't select this compilation option; if you don't choose at all, the value of the configuration variable is empty. 2.3 Rules.make variable
As mentioned earlier, Rules.make is a compilation rule file, and all Makefile includes rules.make. The rules.make file defines a lot of variables, most important to compile, link list variables.
O_OBJS, L_OBJS, OX_OBJS, LX_OBJS: This directory needs to be compiled into the list of target files for Linux kernel VMLinux, where "X" in OX_OBJS and LX_OBJS indicates that the target file uses the export_symbol output symbol.
M_OBJS, MX_OBJS: This directory needs to be compiled into a list of target files that can be loaded. Similarly, "X" in MX_OBJS indicates that the target file uses the export_symbol output symbol.
O_target, l_target: There is an o_target or l_target in each subdirectory, and Rules.make first recombines all target files in O_OBJS and OX_OBJS from source code, and then link them into an o_target or l_target using $ (ld) -r. O_Target ends with .o, and l_target ends.
2.4 subdirectory Makefile
Subdate Makefile is used to control the compilation rules for the source code below this level. We use an example to explain the composition of Makefile:
#
# Makefile for the Linux kernel.
#
# All of the (potential) Objects That Export Symbols.
# This list comes from 'grep -l export_symbol *. [Hc]'.
Export-objs: = tc.o
# Object File Lis.
Obj-y: =
Obj-m: =
Obj-n: =
Obj-: =
Obj - $ (config_tc) = tc.o
Obj - $ (config_zs) = zs.o
Obj - $ (config_vt) = lk201.o lk201-map.o lk201-remap.o
# FILES THAT ARE Both Resident and Modular: Remove from Modular.
Obj-M: = $ (Filter-Out $ (OBJ-Y), $ (OBJ-M))
# Translate to rules.make lists.
L_target: = tc.a
L_objs: = $ (Sort $ (Filter-Out $ (Export-Objs), $ (OBJ-Y)))
LX_OBJS: = $ (Sort $ (Filter $ (Export-Objs), $ (OBJ-Y)))
M_objs: = $ (Sort $ (Filter-Out $ (Export-Objs), $ (OBJ-M))) MX_OBJS: = $ (Sort $ (Filter $ (EXPORT-OBJS), $ (OBJ-M))))))
INCLUDE $ (TOPDIR) /Rules.make
a) Note The description and explanation of makefile, starting from #.
b) Compilation Target Definition Similar to OBJ - $ (config_tc) = Tc.o's statement is the most important part of the child directory Makefile. Compilation Target Definitions those list of target files in the Linux kernel in this subdirectory. In order to compile only this feature only, all target definitions combine the judgment of the configuration variable. As mentioned earlier, each configuration variable range is: Y, N, M and empty, OBJ - $ (config_tc) corresponds to OBJ-Y, OBJ-N, OBJ-M, OBJ-. If config_tc is configured as y, Tc.o enters the OBJ-Y list. Obj-y is a list of target files containing the Linux kernel VMLinux; OBJ-M is a list of target files compiled into a module; the list of files in OBJ-N and OBJ-Ignore is ignored. The configuration system compiles and links according to the properties of these lists. The target file in Export-Objs uses export_symbol () to define a common symbol to load the module. At the last part of the Tc.c file, there is "export_symbol (search_tc_card);" indicating that Tc.o has a symbol output. It is to be pointed out here that there are two formats for the definition of the compilation target, which is old-fashioned and newly defined. The old-fashioned definition is those variables used in front of Rules.make, the new definition is OBJ-Y, OBJ-M, OBJ-N and OBJ-. Linux kernel recommends using new definitions, but because rules.make does not understand new definitions, it is necessary to convert it into an old-fashioned definition in the adapter segment in Makefile.
c) The function of the adapter section adapter segment is to convert the new definition into an old-fashioned definition. In the above example, the adaptation segment is L_Target, L_OBJS, LX_OBJS, M_OBJS, MX_OBJS, which converts OBJ-Y and OBJ-M to Rules.make, which can be understood. L_objs: = $ (Sort $ (Filter-Out $ (Export-Objs), $ (OBJ-Y))) Defines the way to build l_objs: Filter out Export-Objs (Tc.o) in the list of OBJ-Y , Then sort and remove the repeated file name. Some special functions of GNU Make are used here, and the specific meaning can be referred to the Make document (INFO MAKE).
d) Include $ (TOPDIR) /Rules.make
3. Profile
3.1 Configuration function overview
In addition to the writing of Makefile, another important job is to add new features to Linux configuration options, provide instructions for this feature, allowing users to choose this feature. All of these needs to write configuration scripts in config.in files, in the Linux kernel, have a variety of ways:
Configuration command interpreter script Make config, make oldconfigscripts / ConfigureMake menuconfigscripts / MenuconfigMake xconfigscripts / tkparse character-based interface to configure (make config), for example, the top-level Makefile to call scripts / Configure, to be configured in arch / arm / config.in. After the command is executed, the file is generated. Config, which saves configuration information. Next time make config will produce a new .config file, the original .config is renamed .config.OLD
3.2 Configuring Language
1) The top menu MainMenu_name / prompt / / prompt / is the value of the reference variable in '...' by 'or "surrounded strings,' and". MainMenu_name sets the name of the highest layer menu, which is only displayed when Make Xconfig.
2) Inquiry statement
BOOL / PROMPT / / SYMBOL /
HEX / Prompt / / Symbol / / Word /
INT / PROMPT / / SYMBOL / / WORD /
String / Prompt / / Symbol / / Word /
Tristate / Prompt / / Symbol /
Inquiry statement first displays a stroke / prompt /, waiting for user input, and assigns the input result to the configuration variable represented by / symbol. The difference between different interrogation statements is that they are accepted differently, such as Bool accepts Boolean type (Y or N), HEX accepts 16 credit data. Some query statements have the third parameter / word / for a default.
3) Define statement
Define_Bool / Symbol / / Word /
Define_Hex / Symbol / / Word /
Define_INT / Symbol / / Word /
Define_String / Symbol / / Word /
Define_tristate / Symbol / / Word /
Unlike the query statement waits for user input, define the statement explicitly gives the configuration variable / symbol / assignment / Word /.
4) Dependency
DEP_BOOL / Prompt / / / Symbol / / DEP / ...
DEP_MBOOL / PROMPT / / SYMBOL / / DEP / ...
Dep_Hex / Prompt / / Symbol / / Word / / / DEP / ...
DEP_INT / Prompt / / / / / / / / / / / / / ...
Dep_String / Prompt / / Symbol / / Word / / / / DEP / ...
Dep_tristate / prompt / / symbol / / dep / ...
Similar to inquiry statements, dependent statements are also defined new configuration variables. Different, the configuration variable / symbol / value range will depend on the configuration variable list / dep / .... This means that the corresponding function of the defined configuration variable depends on the selection of the corresponding functionality depending on the list. Take DEP_BOOL as an example, if all the configuration variables of the / DEP / ... are all value Y, the / prompt /, the user can enter any value to configure variable / symbol /, but as long as there is a configuration variable value N Then / Symbol / is forced to be n. The difference between different dependent statements is different from the range of values generated by dependent conditions. 5) Select a statement
Choice / Prompt / / Word / / Word /
The Choice statement first gives a string of selection list for users to select one. For example, Linux for ARM supports a variety of ARM CEE-based CPUs, Linux provides a CPU list with the Choice statement for users to choose from:
Choice 'ARM SYSTEM TYPE' /
"Anakin Config_arch_anakin /
Archimedes / A5000 Config_arch_arca5k /
Cirrus-Cl-PS7500fe config_arch_clps7500 /
......
SA1100-BASED CONFIG_ARCH_SA1100 /
Shark config_arch_shark "RISCPC
Choice first displays / prompt /, and then breaks / Word / decomposes to two parts, the front portion is the corresponding selected prompt, and the rear portion is the corresponding selection configuration variable. The configuration variable selected by the user is Y, the rest is n.
6) IF statement
IF [/ expr /]; then
/ Statement /
...
Fi
IF [/ expr /]; then
/ Statement /
...
Else
/ Statement /
...
Fi
The IF statement is judged for the configuration variable (or a combination of variables) and makes different processing. The determination condition / EXPR / can be a single configuration variable or string or an expression of the operator. Operators are: =,! =, - O, -A, etc.
7) Menu Block statement
MainMenu_Option next_comment
Comment '... ..'
...
Endmenu
Introduce a new menu. After adding a new feature to the kernel, you need to add a new menu accordingly and give the configuration options for this feature under the new menu. Comment is the name of the new menu. All configuration option statements that belong to this menu are written between Comment and endmenu.
8) Source Statement Source / Word // Word / is the file name, and the role of Source is to transfer new files.
3.3 Default configuration
The Linux kernel supports a lot of hardware platforms. For specific hardware platforms, some configurations are required, and some configurations are not required. In addition, the normal operation of newly added functions often requires certain prerequisites, for new functions, must be configured. Therefore, the particular hardware platform can function properly corresponding to a minimum basic configuration, which is the default configuration.
There is a default configuration for each Arch in the Linux core. After adding a new feature to the kernel code, if the new feature is required for this Arch, it is necessary to modify the default configuration of this ARCH. The modification method is as follows (in the Linux kernel root directory): Backup .config file cp arch / arm / deconfig .config modified .config cp .config arch / arm / deconfig recovery .config
If the new features apply to many Arch, as long as the specific ARCH, repeat the steps above.
3.4 Help File
Everyone has this experience. When configuring the Linux kernel, encounter configuration options that you don't understand, you can view its help, from which you can get the suggestions. Let's take a look at how to add help information to a configuration option.
Help information for all configuration options is in documentation / configure.help, its format is:
4. Example
For a developer, add the kernel code developed to the Linux kernel, there is three steps. First, determine the location of your own development code into the kernel; secondly, add your own functions to the Configuration options for your Linux kernel, users can choose this feature; Finally, construct the subdirectory Makefile, according to the user's choice, will The code is compiled into the finally generated Linux kernel. Below, we will explain how to add new features to the Linux core through a simple example - Test Driver, combined with the previous knowledge.
4.1 directory structure
Test Driver is placed in drivers / test / directory:
$ CD Drivers / Test
$ TREE
.
| - Config.in
| - Makefile
| - CPU
| | - Makefile
| `- cpu.c
| - Test.c
| - Test_Client.c
| - Test_ioctl.c
| - Test_Proc.c
| - Test_Queue.c
`- test
| - Makefile
`- Test.c
4.2 Profile
1) Drivers / Test / Config.in
#
# Test Driver Configuration
#
MainMenu_Option next_comment
Comment 'Test Driver'
Bool 'Test Support' Config_Test
IF [$ config_test "=" y "]; then
Tristate 'Test User-Space Interface' config_test_user
BOOL 'TEST CPU' config_test_cpu
Fiendmenu
Since Test Driver is a new feature for kernel, first create a menu Test Driver. Then, "Test Support" is displayed, waiting for user selection; then determine if the user selects Test Driver, if (config_test = y), further display subunies: user interface and CPU function support; due to user interface functions can be compiled It is a kernel module, so the inquiry statement here uses Tristate (because the value range of Tristate includes Y, N, M, M correspond to the module).
2) Arch / arm / config.in At the end of the file: Source Drivers / Test / Config.in, incorporating the configuration of the Test Driver substructure into the Linux kernel configuration.
4.3 Makefile
1) Drivers / Test / Makefile
# Drivers / Test / Makefile
#
# Makefile for the test.
#
SUB_DIRS: =
MOD_SUB_DIRS: = $ (SUB_DIRS)
All_sub_dirs: = $ (SUB_DIRS) CPU
L_target: = Test.a
Export-objs: = Test.o test_client.o
Obj - $ (config_test) = Test.o test_queue.o test_client.o
Obj - $ (config_test_user) = Test_iocTl.o
Obj - $ (config_proc_fs) = Test_Proc.o
Subdir - $ (config_test_cpu) = CPU
INCLUDE $ (TOPDIR) /Rules.make
Clean:
For Dir In $ (all_sub_dirs); do make -c $$ dir clean; done
RM -F *. [OA]. *. Flags
The final generated target file in the Drivers / Test directory is Test.a. Export_Symbol output symbols in Test.c and Test-Client.c, so Test.o and Test-Client.o are located in the Export-Objs list. Then, according to the selection of the user (specifically, the value of the configurable variable), the respective corresponding OBJ- * list is constructed. Due to the Test Driver, a subdirectory CPU is included, when config_test_cpu = y (ie, the user selects this feature), you need to add the CPU directory into the SubDIR-Y list.
2) Drivers / Test / CPU / Makefile
# Drivers / Test / Test / Makefile
#
# Makefile for the test CPU
#
SUB_DIRS: =
MOD_SUB_DIRS: = $ (SUB_DIRS)
All_sub_dirs: = $ (SUB_DIRS)
L_target: = Test_cpu.a
Obj - $ (config_test_cpu) = cpu.o
INCLUDE $ (TOPDIR) /Rules.make
Clean:
RM -F *. [OA]. *. Flags3) Drivers / Makefile
......
Subdir - $ (config_test) = TEST
......
INCLUDE $ (TOPDIR) /Rules.make
Add subDir - $ (config_test) = TEST in DRIVERS / Makefile, so that after the user selects the test driver function, the TEST directory can be entered when the kernel compiles.
4) Makefile
......
Drivers - $ (config_pld) = Drivers / PLD / PLD.O
Drivers - $ (config_test) = Drivers / Test / Test.a
Drivers - $ (config_test_cpu) = drivers / test / CPU / TEST_CPU.A
Drivers: = $ (drivers-y)
......
DRIVERS - $ (config_test) = Drivers / Test / Test.a and Drivers / Test / CPU / TEST_CPU.A were joined in the top Makefile. How can users choose Test Driver, then config_test and config_test_cpu are all in the DRIVERS-Y list, and then placed in the DRIVERS list. In the previous mention, Linux kernel file VMLinux includes Drivers, so test.a and test_cpu.a will eventually be linked to VMLinux.
5. reference
Document / kbuild / makefiles.txt, Linux Kernel Source code Document / kbuild / config-language.txt, Linux Kernel Source code Contributing to the Linux Kernel - The Linux Configuration System, Linux Journal, http: //www.linuxjournal.com /categories.php?op=newindex&catid=178 unreliable guide to hacking the linux kernel, paul rusty russell, rusty @ rustcorp.com.au
About author
Tang Kai, you can contact him through tangk73@hotmail.com.