Linux Kernel configuration System Analysis
[Excerpted from http://www-900.ibm.com]
With the wide application of Linux operating systems, especially the development of Linux in the embedded field, more and more people are devoted to Linux kernel-level development. Faced with the ever-growing Linux kernel source code, developers will face the same problem after completing their own kernel code, that is, how to integrate the source code into the Linux kernel, add the corresponding Linux configuration options and finally compile them into the Linux kernel. Therefore, you need to understand the Linux Kernel configuration system.
As we all know, the Linux kernel is developed by Linux fans around the world. linux kernels face many new changes every day. However, the Linux kernel is not organized in disorder, but is very concise and scalable. developers can easily add new content to the Linux kernel. One of the reasons is that linux adopts a modular Kernel configuration system to ensure kernel scalability.
This article first analyzes the Configuration System Structure in the Linux kernel, then explains the formats of makefile and configuration files, as well as the meaning of the configuration statement, and finally, through a simple example-test driver, describes how to add self-developed code to the Linux kernel. In the following article, it is impossible to explain all the functions and commands, just to explain those commonly used ones. For those not discussed, please refer to the relevant literature.
1. Configure the basic structure of the system
The Linux Kernel configuration system consists of three parts:
1. makefile: makefile distributed in the source code of the Linux kernel, which defines the compiling rules of the Linux kernel;
2. configuration file (config. In): provides users with the configuration selection function;
3. Configuration tool: includes the configuration command interpreter (which explains the configuration commands used in the configuration script) and the configuration user interface.
The ncurses graphic interface and the user configuration interface based on the xwindows graphic interface correspond to make config, make menuconfig, and make xconfig respectively ).
These configuration tools are all written in scripting languages, such as Tcl/TK and Perl (including some code written in C ). This document does not analyze the Configuration System, but describes how to use the configuration system. Therefore, unless it is the maintainer of the Configuration System, General kernel developers do not need to understand their principles. They only need to know how to compile makefile and configuration file. Therefore, in this article, we will only discuss makefile and configuration file. In addition, we take arm as an example for all the content related to the specific CPU architecture. In this way, we can not only clarify the problems discussed, but also have no impact on the content itself.
2. makefile
2.1 makefile Overview
Makefile is used to construct a list of source files to be compiled based on the configuration, compile them separately, and link the target code together to form a Linux kernel binary file.
Since the Linux kernel source code is organized in a tree structure, makefile is also distributed in the directory tree. Makefile in Linux kernel and files directly related to makefile include:
1. makefile: the top-level makefile, which is the overall control file for Kernel configuration and compilation.
2. config: The Kernel configuration file, including the configuration options selected by the user, used to store the Kernel configuration results (such as make config ).
3. Arch/*/makefile: makefile located in various CPU system directories, such as ARCH/ARM/makefile, is a makefile for a specific platform.
4. makefile under each subdirectory: for example, drivers/makefile, responsible for managing the source code under the subdirectory.
5. Rules. Make: Rule file, which is used by all makefiles.
After you use make config to configure, A. config is generated. Select the configuration for reading the top-level makefile into. config. The top-level makefile has two main tasks: generate the vmlinux file and the kernel module ). To achieve this, the top-level makefile recursively enters each subdirectory of the kernel and calls makefile in these subdirectories respectively. The subdirectories are determined by the Kernel configuration. In the top-level makefile, include ARCH/$ (ARCH)/makefile, which contains the makefile under the specific CPU architecture.
Contains information about the platform. Makefile in each subdirectory is also based on. the configuration information provided by config constructs the list of source files required for the current configuration, and includes $ (topdir)/rules at the end of the file. make.
The rules. Make file plays an important role in defining the compilation rules shared by all makefiles. For example, if you need to compile all C Programs in the current directory into assembly code, you need to have the following compilation rules in makefile:
%. S: %. c
$ (CC) $ (cflags)-S $ <-o $ @
Many Sub-directories have the same requirements, so you need to include this compilation rule in their makefiles, Which is troublesome. In Linux, such compilation rules are uniformly placed in rules. make, and include the rules in their makefiles. make (include rules. make) to avoid repeating the same rules in multiple makefiles. For the above example, the rule in rules. Make is:
%. S: %. c
$ (CC) $ (cflags) $ (extra_cflags) $ (cflags _ $ (* F) $ (cflags _ $ @)-S $ <-o $ @
2.2 variables in makefile
The top-level makefile defines and outputs many variables to the environment, and transmits some information to makefiles in each subdirectory. Some variables, such as subdirs, are defined in the top-level makefile and assigned the initial values. They are also expanded in arch/*/makefile.
Common variables include the following types:
1) version information
Version information includes: version, patchlevel, sublevel, extraversion, and kernelrelease. Version Information defines the current kernel version, such as version = 2, patchlevel = 4, sublevel = 19, exataversion =-rmk7, which together constitute the kernel release version kernelrelease: 2.4.19-rmk7
2) CPU architecture: arch
At the beginning of the makefile on the top layer, arch is used to define the architecture of the target CPU, such as arch: = arm. In makefile of many sub-directories, You must select the list of source files to be compiled according to the arch definition.
3) path information: topdir, subdirs
Topdir defines the root directory of the Linux kernel source code. For example, makefile in each subdirectory can locate rules. Make by using $ (topdir)/rules. Make.
Subdirs defines a directory list. When compiling a kernel or module, the top-level makefile determines which subdirectories to enter based on subdirs. The value of subdirs depends on the Kernel configuration. In the top-level makefile, the value of subdirs is kernel drivers mm FS net IPC Lib. According to the Kernel configuration, the value of subdirs is expanded in arch/*/makefile. See the example in 4.
4) kernel composition information: Head, core_files, networks, drivers, Libs
The vmlinux Kernel File 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 \
$ (Core_files )\
$ (Drivers )\
$ (Networks )\
$ (Libs )\
-- End-group \
-O vmlinux
We can see that vmlinux is composed of head, Main. O, version. O, core_files, drivers, networks, and libs. These variables (such as head) are used to define the target file and library file list generated by the connection in vmlinux. The head is defined in arch/*/makefile to determine the list of files first linked to vmlinux. For example, for the cpu Of the ARM Series, the head is defined:
Head: = ARCH/ARM/kernel/head-$ (processor). O \
ARCH/ARM/kernel/init_task.o
It indicates that head-$ (processor). O and init_task.o must 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-level makefile, and are expanded by arch/*/makefile as needed. Core_files corresponds to the core file of the kernel, including kernel/kernel. o, mm/mm. o, FS/Fs. o, IPC/IPC. o, we can see that these are the most important files in the kernel.
In addition, arch/ARM/makefile expands core_files:
# Arch/ARM/makefile
# If we have a machine-specific directory, then include it in the build.
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. o arch/ARM/MM/mm. o $ (core_files)
Libs: = ARCH/ARM/lib. A $ (libs)
5) Compilation information: CPP, CC, As, LD, AR, cflags, linkflags
In rules. Make, general compilation rules are defined. In specific scenarios, the compilation environment must be clearly defined. The compilation environment is defined in the preceding variables. Cross_compile is defined for cross-compilation requirements. For example:
Cross_compile = arm-uclibc-
Cc = $ (cross_compile) GCC
LD = $ (cross_compile) LD
......
Cross_compile defines the prefix of the Cross-compiler Arm-uclibc-, indicating that all cross-compiler tools start with arm-uclibc-. Therefore, before each cross-compiler tool, $ (cross_compile) is added to form a complete cross-compilation tool file name, such as arm-Linux-GCC.
Cflags defines the parameters passed to the C compiler.
Linkflags is the parameter used by the linker when the link is used to generate vmlinux. Linkflags in ARM/*/makefile
For example:
# Arch/ARM/makefile
Linkflags: =-p-X-t arch/ARM/vmlinux. LDS
6) configure the variable config _*
The. config file contains many configuration variable equations to describe the user configuration results. For example, config_modules = y indicates that the module function of the Linux kernel is selected.
. After being contained by the top-level makefile, many configuration variables are formed. Each configuration variable has a fixed value: Y indicates that the kernel code corresponding to the current compilation option is statically compiled into the Linux kernel; M indicates that the kernel code corresponding to the current compilation option is compiled into a module. N indicates that this compilation option is not selected. If no selection is made, the value of the configuration variable is null.
2.3 rules. Make variable
As mentioned above, rules. Make is the compilation rule file, and all makefiles will include rules. Make. The rules. Make file defines many variables. The most important is the compilation and link list variables.
O_objs, l_objs, ox_objs, and lx_objs: the target file list of the Linux kernel vmlinux needs to be compiled in this directory. "X" in ox_objs and lx_objs indicates that the target file uses the export_symbol output symbol.
M_objs, mx_objs: the target file list under the local directory that needs to be compiled into a loadable module. Similarly, "x" in mx_objs indicates that the target file uses the export_symbol output symbol.
O_target, l_target: Each subdirectory has an o_target or l_target, rules. Make
Compile the source code to generate all the target files in o_objs and ox_objs, and then use $ (LD)-R to link them into an o_target or l_target. O_target ends with. O, while l_target ends with..
2.4 subdirectory makefile
The subdirectory makefile is used to control the compilation rules of the source code below the current directory. An example is provided to illustrate the sub-directories.
Makefile composition:
#
# 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 lists.
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.
Rochelle target: = tc.
Rochelle 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) annotations
Description and explanation of makefile, starting from.
B) Compile the target definition
Statements similar to OBJ-$ (config_tc) + = tc. O are used to define the compilation target and are the most important part of the subdirectory makefile. The compilation target defines the target file list that needs to be compiled into the Linux kernel under the sub-directory. In order to compile only after the user selects this function, all target definitions combine the judgment on configuration variables.
As mentioned above, the value range of each configuration variable is Y, n, m, and null. obj-$ (config_tc) corresponds to OBJ-y, obj-N, obj-m, respectively, OBJ -. If config_tc is configured as Y, TC. O enters the obj-y list. OBJ-Y is the list of target files included in the Linux Kernel vmlinux, obj-m is the list of target files compiled into modules, and obj-N and obj-are ignored. The configuration system compiles and links these lists based on their attributes.
The target files in export-objs all use export_symbol () to define public symbols so that they can be used by the load module. In the last part of the TC. c file, there is "export_symbol (search_tc_card);", indicating that TC. O has signed output.
It should be noted that there are two formats for the definition of the compilation target, namely the old definition and the new definition. The old definition is the variables used by rules. Make. The new definition is obj-y, obj-M, obj-N, and obj -. The new definition is recommended for the Linux kernel, but because rules. Make does not understand the new definition, it is necessary to convert the adaptation segment in the makefile into an old definition.
C) ADAPTATION segment
The adaptation segment is used to convert a new definition into an old definition. In the above example, the adaptation section is to convert obj-y and obj-m to Rochelle. Make to understand l_target, l_objs, lx_objs, m_objs, and mx_objs.
Rochelle objs: = $ (sort $ (filter-out $ (export-objs), $ (obj-y) defines the Rochelle objs generation method: filter out export-objs (TC. o), then sort and remove duplicate file names. Some special functions of GNU make are used here. For specific meanings, refer to the Make document (Info make ).
D) include $ (topdir)/rules. Make
3. Configuration File
3.1 configuration function Overview
In addition to makefile writing, another important task is to add the new function to the configuration options of Linux and provide a description of this function, giving users the opportunity to select this function. All of these scripts must be written in the config. In file using the configuration language. In the Linux kernel, there are multiple configuration commands:
Configure command interpretation script
Make config, make oldconfig scripts/configure
Make menuconfig scripts/menuconfig
Make xconfig scripts/tkparse
Take the character interface configuration (make config) as an example. The top-level makefile calls scripts/configure and is configured according to arch/ARM/config. In. After the command is executed, the file. config is generated, and the configuration information is saved. The next make config operation will generate a new. config file.
. Config is renamed as. config. Old.
3.2 configuration language
1) top menu
Mainmenu_name/prompt // prompt/is a string enclosed by 'or ". The difference between' and" is '... 'You can use $ to reference the variable value. Mainmenu_name sets the name of the top menu, which is only displayed when make xconfig.
2) query statement
Bool/prompt // symbol/
Hex/prompt // symbol // word/
INT/prompt // symbol // word/
String/prompt // symbol // word/
Tristate/prompt // symbol/
The query statement first displays a series of prompts/prompt/, waiting for user input, and assigning the input results to the configuration variables represented by/symbol. Different query statements have different input data types. For example, bool accepts Boolean (Y or N) and hex accepts hexadecimal data. Some query statements have the third parameter/word/, which is used to give the default value.
3) Definition 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 that waits for user input, the definition statement explicitly assigns a value to the configuration variable/symbol/word /.
4) Dependency statements
Dep_bool/prompt // symbol // DEP /...
Dep_mbool/prompt // symbol // DEP /...
Dep_hex/prompt // symbol // word // DEP /...
Dep_int/prompt // symbol // word // DEP /...
Dep_string/prompt // symbol // word // DEP /...
Dep_tristate/prompt // symbol // DEP /...
Similar to the query statement, the dependency statement also defines new configuration variables. The difference is that the value range of the configuration variable/symbol/depends on the configuration variable list/DEP /.... This means that the function Selection of the defined configuration variable depends on the function Selection of the dependency list. Dep _
For bool, if/DEP /... If all configuration variables in the list are set to Y,/prompt/is displayed. You can enter any value to the configuration variable/symbol /, the difference between different dependency statements is that they have different value ranges produced by dependency conditions.
5) select statement
Choice/prompt // word/
The choice statement first provides a list of choices for the user to choose from. For example, Linux for ARM supports a variety of ARM core-based CPUs. Linux uses choice statements to provide a CPU list 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 splits/word/into two parts: the front part is the corresponding selected prompt, and the latter part is the corresponding configuration variable. The selected configuration variable is Y, and the rest are n.
6) If statement
If [/expr/]; then
/Statement/
...
Fi
If [/expr/]; then
/Statement/
...
Else
/Statement/
...
Fi
The IF statement determines the configuration variables (or combinations of configuration variables) and processes them differently. The judgment condition/expr/can be a single configuration variable or string, or an expression with an operator. Operators: = ,! =,-O,-a, and so on.
7) menu BLOCK statement
Mainmenu_option next_comment
Comment '..... '
...
Endmenu
Introduce a new menu. After adding a new function to the kernel, you need to add a new menu and provide configuration options for this function under the new menu. The comment after comment is the name of the new menu. All the 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 source is used to call a new file.
3.3 Default Configuration
Linux
The kernel supports many hardware platforms. For specific hardware platforms, some configurations are required, and some configurations are not required. In addition, the normal operation of new functions also requires certain prerequisites. For new functions, you must configure them accordingly. Therefore, the normal operation of a specific hardware platform corresponds to a minimum basic configuration, which is the default configuration.
The Linux kernel has a default configuration for each arch. After a new feature is added to the kernel code
Required. You must modify the default configuration of this arch. The modification method is as follows (in the Linux Kernel root directory ):
1. Back up the. config file
2. cp arch/ARM/deconfig. config
3. Modify. config
4. CP. config ARCH/ARM/deconfig
5. Restore. config
If the new function applies to many arch types, you only need to repeat the above steps for the specific arch.
3.4 Help File
Everyone has such experience. When you configure the Linux kernel, you can view its help for configuration options that do not understand the meaning, and get the selection suggestions. Next we will look at how to add help information to a configuration option.
The help information for all configuration options is in documentation/configure. Help. The format is:
<Description>
<Variable name>
<Help File>
<Description> name of this configuration option, <variable name> corresponding configuration variable, <Help File>
Corresponding configuration help information. In the help information, first briefly describe this function, and then describe what effect it will have after you select this function. Finally, do not forget to write "if not clear, select N (OR) y "to prompt users who are overwhelmed.
4. Instance
For a developer, adding the self-developed kernel code to the Linux kernel requires three steps. First, make sure to put your development code into the kernel. Second, add the features you have developed to the configuration options of the Linux kernel so that you can select this function. Finally, build the subdirectory makefile and compile the corresponding code into the final generated Linux kernel based on the user's selection. Next, we will explain how to add new functions to the Linux kernel through a simple example, test driver, and the previous knowledge.
4.1 directory structure
The test driver is stored in the 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 configuration file
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
Fi
Endmenu
Because test driver is a new function for the kernel, a menu test driver is created first. Then, "test support" is displayed, waiting for the user to select. Next, determine whether the user has selected the test driver. If it is (config_test = Y), the sub-functions: user interface and CPU functions are further displayed; because the user interface function can be compiled into the kernel module, tristate is used in the query statement here (because the tristate value range includes y, N, and m, and m is the corresponding module ).
2) arch/ARM/config. In
Add source Drivers/test/config. in to the end of the file, and add the configuration of the test driver sub-function to 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
Rochelle target: = test.
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 under the drivers/test directory is test.. The export_symbol output symbol is used in test. C and test-client.c, so test. O and test-client.o are in the export-objs list. Then, based on the user's selection (specifically, the value of the configuration variable), build the corresponding obj-* List. Because the test driver contains a sub-directory CPU, when config_test_cpu = Y (this function is selected), you need to add the CPU directory to the subdir-y list.
2) Drivers/test/CPU/makefile
# Drivers/test/makefile
#
# Makefile for the test CPU
#
Sub_dirs: =
Mod_sub_dirs: = $ (sub_dirs)
All_sub_dirs: = $ (sub_dirs)
Rochelle target: = test_cpu.a
OBJ-$ (config_test_cpu) + = CPU. o
Include $ (topdir)/rules. Make
Clean:
Rm-f *. [OA]. *. flags
3) Drivers/makefile
......
Subdir-$ (config_test) + = test
......
Include $ (topdir)/rules. Make
Add subdir-$ (config_test) + = test to drivers/makefile to enable the kernel to enter the test directory after the test driver function is selected.
4) makefile
......
Drivers-$ (config_pld) + = Drivers/PLD. o
Drivers-$ (config_test) + = Drivers/test.
Drivers-$ (config_test_cpu) + = Drivers/test/CPU/test_cpu.a
Drivers: = $ (drivers-y)
......
Add drivers-$ (config_test) + = Drivers/test. A and drivers-$ (config_test_cpu) + = Drivers/test/CPU/test_cpu.a to the top-level makefile. If you select test driver, both config_test and config_test_cpu are y, test. A and test_cpu.a are both in the drivers-y list, and then placed in the drivers list. As mentioned earlier, the Linux Kernel File vmlinux
The components include drivers, so test. A and test_cpu.a can finally be linked to vmlinux.