Linux Kernel configuration System Analysis

Source: Internet
Author: User
Linux Kernel configuration system analysis-general Linux technology-Linux technology and application information. The following is a detailed description. 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 all over the world. The Linux kernel is subject to many new changes every day. However, the organization of the Linux kernel is not messy, but 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 not possible to explain all the functions and commands. You can only explain the commonly used functions. For those that have not been discussed, please refer to the references below.
1. Configure the basic structure of the system
The Linux Kernel configuration system consists of three parts:
Makefile: Makefile distributed in the source code of the Linux kernel, which defines the compiling rules of the Linux kernel;
Config. in: provides you with the configuration selection function;
Configuration tool: includes the configuration command interpreter (explains the configuration commands used in the configuration script) and configure the user interface (the user configuration interface based on the Character interface, the Ncurses-based GUI, And the Xwindows-based GUI, corresponding to Make config, Make menuconfig, and make xconfig ).
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.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:
Makefile: the top-level Makefile, which is the overall control file for Kernel configuration and compilation.
. Config: The Kernel configuration file, including the configuration options selected by the user, used to store the Kernel configuration results (such as make config ).
Arch/*/Makefile: Makefile located in various CPU system directories, such as arch/arm/Makefile, is a Makefile for a specific platform.
Makefile under each subdirectory: for example, drivers/Makefile, responsible for managing the source code under the subdirectory.
Rules. make: Rule file, 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 Makefile under the specific CPU architecture. This Makefile contains platform-related information.
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 = 18, EXATAVERSION =-rmk7, which together constitute the kernel release version kernelrelease: 2.4.18-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. 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-linux-
CC
= $ (CROSS_COMPILE) gcc
LD
= $ (CROSS_COMPILE) ld
......
CROSS_COMPILE defines the prefix of the Cross-compiler arm-linux-, indicating that all the cross-compiler tools start with arm-linux-. 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 are defined 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 first generates all the target files in O_OBJS and OX_OBJS from the source code compilation, and then uses $ (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. Let's use an example to explain the composition of the subdirectory 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 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 list of target files that need to be compiled to the Linux kernel in 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 -. We recommend that you use a new definition in the Linux kernel. However, because Rules. make does not understand the new definition, You need 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 methods to configure 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. The original. 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. Take dep_bool as an example. If/dep /... If the values of all configuration variables in the list are y,/prompt/is displayed. You can enter any value to the configuration variable/symbol/, but if the value of one configuration variable is n, then/symbol/is forced to n.
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 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 function is added to the kernel code, if the new function is required for this ARCH, You need to modify the default configuration of this ARCH. The modification method is as follows (in the Linux Kernel root directory ):
Back up the. config file
Cp arch/arm/deconfig. config
Modify. config
Cp. config arch/arm/deconfig
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 configuring the Linux kernel, you can view the help of configuration options that do not understand the meaning of the configuration, and you can 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:



Name of the configuration option, Corresponding configuration variables, 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 includes DRIVERS, so test. a and test_cpu.a can finally 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,



Magpie nest invited experts: Fengyun
For more information, see http://www.xique5.cn/. in this post, visit http://www.xique5.cn/viewthread.php? Tid = 1844
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.