> php教程 > PHP开发 > 본문

Linux 커널 구성, 컴파일 및 Makefile 간략한 소개

高洛峰
풀어 주다: 2016-12-01 15:41:49
원래의
1572명이 탐색했습니다.

안녕하세요 여러분! 저는 CrazyCatJack입니다. 최근에는 Linux 커널의 구성, 컴파일 및 Makefile을 배우고 있습니다. 오늘은 학습결과를 요약해서 공유해드리겠습니다 ^_^

1. 압축해제 및 패치

먼저, 구한 리눅스 커널의 압축을 풀어주세요. 여기서는 linux.2.22.6 버전의 커널을 사용하고 있습니다. Linux에서 명령줄을 사용하여 tar xjf linux.2.22.6.tar.bz2를 통해 커널의 압축을 풉니다. 그런 다음 이 커널을 패치해야 하는 경우 패치 명령(patch -px <../linux.2.22.6.patch)을 사용하십시오. 여기서 px는 패치 파일에 설명된 슬래시를 무시한다는 의미입니다. 즉, 첫 번째 x 디렉터리를 무시합니다.

--- linux-2.6.22.6/arch/arm/configs/s3c2410_defconfig+++ linux-2.6.22.6_jz2440/arch/arm/configs/s3c2410_defconfig

현재 커널의 루트 디렉터리, 즉 linux-2.6.22.6에 있다면 패치 시 슬래시 디렉터리를 무시해야 한다는 뜻입니다. 그런 다음 패치 명령은 patch -p1 <../linux.2.22.6.patch입니다.

2. 커널 구성

이제 패치가 적용되었으므로 다음 단계는 커널을 구성하는 것입니다. 여기에는 세 가지 구성 방법이 있습니다.

 1> 이것은 가장 번거로운 방법이며 모든 구성을 사용자가 수행해야 합니다.

2> 기본 구성을 직접 수정합니다. 즉, defconfig 파일을 수정합니다. 아키텍처에 대한 기본 구성 파일을 찾으려면 find -name "*defconfig*"를 사용하십시오. Arch/arm/configs에서 내 보드의 기본 구성 파일을 찾았습니다. defconfig 파일을 실행합니다: make XXX_defconfig. XXX는 사용 중인 특정 보드 모델입니다. 이 작업을 수행한 후 결과는 .config 파일에 저장됩니다. 그런 다음 make menuconfig 명령을 실행합니다. 이번 구성은 기본 구성을 약간 수정한 것뿐입니다.

 3>제조업체의 구성 파일을 사용하세요. 하드웨어에 제조업체에서 제공한 구성 파일이 있는 경우 가장 쉽습니다. 직접 cp XXX.config. 그런 다음 make menuconfig를 실행합니다.

여기서는 커널 구성에 대해 자세히 알려드리겠습니다. Linux 커널 구성은 .config 파일을 생성하는 것입니다. 컴파일 중에 다른 관련 구성 파일을 생성하려면 .config 파일을 사용해야 하기 때문입니다. 예를 들어 대부분의 구성 항목은 CONFIG_XXXDRIVER입니다. 여기서 XXXDRIVER는 다양한 드라이버를 나타냅니다. 이러한 드라이버가 커널로 컴파일되었는지, 아니면 모듈로 컴파일되었는지 커널에 알려야 합니다. CONFIG_XXXDRIVER를 검색하면

1>C 소스 코드

2>Subdirectory Makefile:drivers/XXX/Makefile

3> include/config/auto.conf

 4>include/linux/autoconf.h

  첫 번째 설명은 다음과 같습니다. .config 파일은 커널 컴파일 중에 include/config를 생성합니다(make uImage) / auto.conf 및 include/linux/autoconf.h. C 소스 코드를 살펴보면 CONFIG_XXXDRIVER가 상수와 동일한 매크로 정의라는 것을 알 수 있습니다. include/linux/autoconf.h의 매크로 정의 CONFIG_XXXDRIVER는 상수이며 0 또는 1일 수 있습니다. 이제 질문이 있습니다. CONFIG_XXXDRIVER가 커널로 컴파일됩니까, 아니면 모듈로 컴파일됩니까? C 언어에서는 구별할 수 없습니다. 이 구별은 어디에 반영됩니까? 이러한 구별은 하위 디렉터리의 Makefile 파일에 반영됩니다. 하위 디렉터리의 Makefile에 obj -y += XXX.o가 있으면 XXX.c가 커널로 컴파일된다는 의미이고, obj -m +=XXX.o는 XXX가 모듈로 컴파일된다는 의미입니다. XXX.ko. include/config/auto.conf 파일은 CONFIG_XXXDRIVER에 값을 할당하는데, y이면 커널에 컴파일된다는 의미이고, m이면 독립된 모듈로 컴파일된다는 뜻이다.

#这里是include/config/auto.conf的部分内容
# Automatically generated make config: don&#39;t edit
# Linux kernel version: 2.6.22.6
# Sun Nov 27 18:34:38 2016
#
CONFIG_CPU_S3C244X=y
CONFIG_CPU_COPY_V4WB=y
CONFIG_CRYPTO_CBC=y
CONFIG_CPU_S3C2410_DMA=y
CONFIG_CRYPTO_ECB=m
CONFIG_SMDK2440_CPU2440=y
로그인 후 복사
#这里是drivers/i2c/Makefile
# Makefile for the i2c core.
#

obj-$(CONFIG_I2C_BOARDINFO)    += i2c-boardinfo.o
obj-$(CONFIG_I2C)        += i2c-core.o
obj-$(CONFIG_I2C_CHARDEV)    += i2c-dev.o
obj-y                += busses/ chips/ algos/

ifeq ($(CONFIG_I2C_DEBUG_CORE),y)
EXTRA_CFLAGS += -DDEBUG
endif
로그인 후 복사

3. 커널 컴파일
위의 설명을 보면 각 드라이버 아래에 Makefile 파일이 있다는 것을 알 수 있습니다. 이 드라이버가 커널로 컴파일되는지 아니면 모듈로 컴파일되는지 정의합니다. 여기서 조금 언급하겠습니다. 위에서 우리는 Makefile의 단일 파일이 커널로 컴파일되고 모듈로 컴파일되는 방법에 대해 이야기했습니다. 그런데 파일이 2개 이상이라면 어떻게 작성하나요? 예를 들면 다음과 같습니다. obj -y += a.o b.o는 a.c와 b.c를 커널로 컴파일한다는 의미입니다.

obj -m += ab.o

ab -objs := a.o b.o

는 a.c와 b.c를 하나의 모듈로 컴파일하는 것을 의미할 수 있습니다. a.c는 a.o를 생성하고, b.c는 b.o를 생성하는 과정입니다. a.o와 b.o가 함께 ab.ko를 생성합니다. uboot 시작 커널의 이전 코드 분석에서 커널을 컴파일하여 생성된 uImage는 헤더 + Linux 커널의 두 부분으로 구성된다고 언급했습니다. 이 헤더에는 커널의 로딩 주소, 진입 주소 등 많은 초기화 매개변수 정보가 포함되어 있습니다. 커널을 컴파일할 때 make uImage를 직접 실행할 수 있습니다. 그러면 uImage는 파일에 어떻게 정의되어 있나요? uImage를 생성하는 방법은 무엇입니까?

먼저 Makefile을 검색해 보니 uImage가 arch/arm/Makefile에 있고, 이 아키텍처 디렉터리의 Makefile이 최상위 디렉터리의 Makefile에 포함되어 있는 것을 알 수 있었습니다. 이런 식으로 make uImage를 실행하면 최상위 디렉터리의 Makefile이 아키텍처 하위 디렉터리의 Makefile을 호출하여 커널을 컴파일하고 uImage를 생성할 수 있습니다.

 顶层目录下Makefile中相关命令:
include $(srctree)/arch/$(ARCH)/Makefile
架构目录下Makefile相关命令:
zImage Image xipImage bootpImage uImage: vmlinux
로그인 후 복사

방금 말한 내용은 최상위 Makefile이 아키텍처 디렉터리에 있는 Makefile을 호출하는 것입니다. 아키텍처 디렉터리에 있는 Makefile은 uImage를 생성하고 vmlinux 파일에 의존합니다. 다음으로 vmlinux 파일을 생성하는 방법을 설명하겠습니다. 최상위 Makefile에는 vmlinux를 생성하기 위한 대부분의 명령이 있습니다.

顶层目录Makefile:
init-y        := init/
init-y        := $(patsubst %/, %/built-in.o, $(init-y)) 

core-y        := usr/
core-y        += kernel/ mm/ fs/ ipc/ security/ crypto/ block/
core-y        := $(patsubst %/, %/built-in.o, $(core-y)) 

libs-y        := lib/
libs-y1        := $(patsubst %/, %/lib.a, $(libs-y))
libs-y2        := $(patsubst %/, %/built-in.o, $(libs-y))
libs-y        := $(libs-y1) $(libs-y2) 

drivers-y    := drivers/ sound/
drivers-y    := $(patsubst %/, %/built-in.o, $(drivers-y))   

net-y        := net/
net-y        := $(patsubst %/, %/built-in.o, $(net-y)) = net/built-in.o


vmlinux: $(vmlinux-lds) $(vmlinux-init) $(vmlinux-main) $(kallsyms.o) FORCE

vmlinux-init := $(head-y) $(init-y)
vmlinux-main := $(core-y) $(libs-y) $(drivers-y) $(net-y)
vmlinux-all  := $(vmlinux-init) $(vmlinux-main)
vmlinux-lds  := arch/$(ARCH)/kernel/vmlinux.lds
export KBUILD_VMLINUX_OBJS := $(vmlinux-all)



架构目录Makefile:
zImage Image xipImage bootpImage uImage: vmlinux

head-y        := arch/arm/kernel/head$(MMUEXT).o arch/arm/kernel/init_task.o
로그인 후 복사

  我已经把顶层目录和架构目录下生成vmlinux的命令摘选出来。首先,我们看要想生成vmlinux,需要vmlinux-lds文件、vmlinux-init文件、vmlinux-main文件。其中,vmlinux-lds是链接脚本文件,定义了代码段,数据段的存放位置。这里我们接着往下看,vmlinux-init需要head-y和init-y,通过查看两个Makefile,我们可以得到经过转换后的结果:

head-y        := 
arch/arm/kernel/head$(MMUEXT).o    arch/arm/kernel/init_task.o

init-y        := $(patsubst %/, %/built-in.o, $(init-y)) = init/built-in.o

core-y        := $(patsubst %/, %/built-in.o, $(core-y)) 
                         = usr/built-in.o kernel/built-in.o mm/built-in.o fs/built-in.o ipc/built-in.o security/built-in.o crypto/built-in.o block/built-in.o

libs-y        := $(libs-y1) $(libs-y2) =lib/lib.a lib/built-in.o

drivers-y    := $(patsubst %/, %/built-in.o, $(drivers-y)) = drivers/built-in.o  sound/built-in.o  

net-y        := $(patsubst %/, %/built-in.o, $(net-y)) = net/built-in.o
로그인 후 복사

  现在已经分析了内核编译的全部过程。那怎样知道我们分析的到底对不对,通过实际执行make uImage我们就可以看到执行过程。这是执行make uImage过程中的部分相关命令:

arm-linux-ld -EL  -p --no-undefined -X -o vmlinux 
-T arch/arm/kernel/vmlinux.lds 
arch/arm/kernel/head.o 
arch/arm/kernel/init_task.o  init/built-in.o --start-group  usr/built-in.o  arch/arm/kernel/built-in.o  arch/arm/mm/built-in.o
로그인 후 복사

  可以看到,首先目标要生成vmlinux,然后是链接脚本为vmlinux.lds。开始生成第一个文件:head.o,第二个文件:init_task.o。这和我们分析的完全一致。接下来以此类推,和我们分析的相同,也就是说我们分析的是正确的。

SECTIONS
{



 . = (0xc0000000) + 0x00008000;

 .text.head : {
  _stext = .;
  _sinittext = .;
  *(.text.head)
 }

 .init : { /* Init code and data        */
   *(.init.text)
  _einittext = .;
  __proc_info_begin = .;
   *(.proc.info.init)
  __proc_info_end = .;
  __arch_info_begin = .;
   *(.arch.info.init)
  __arch_info_end = .;
  __tagtable_begin = .;
   *(.taglist.init)
  __tagtable_end = .;
  . = ALIGN(16);
  __setup_start = .;
   *(.init.setup)
  __setup_end = .;
  __early_begin = .;
   *(.early_param.init)
  __early_end = .;
  __initcall_start = .;
로그인 후 복사

  这是链接脚本vmlinux.lds中的部分内容。首先定义了虚拟地址:(0xc0000000) + 0x00008000。 然后是首先执行头部文件,这与我们分析的完全一致。代码段,初始化代码段等等。

  这就是Linux内核的从配置到编译的全部分析了^_^


관련 라벨:
원천:php.cn
본 웹사이트의 성명
본 글의 내용은 네티즌들의 자발적인 기여로 작성되었으며, 저작권은 원저작자에게 있습니다. 본 사이트는 이에 상응하는 법적 책임을 지지 않습니다. 표절이나 침해가 의심되는 콘텐츠를 발견한 경우 admin@php.cn으로 문의하세요.
인기 추천
인기 튜토리얼
더>
최신 다운로드
더>
웹 효과
웹사이트 소스 코드
웹사이트 자료
프론트엔드 템플릿