시작 중 initramfs gzip의 cpio 아카이브에 대한 주소 지정 체계

시작 중 initramfs gzip의 cpio 아카이브에 대한 주소 지정 체계

Linux 커널 v2.6.21.7(vmlinux64)용 다음 부팅 파일(배포: MIPS64용 Cavium-Octeon):

ELF HEADER:
------------------------------------------
Magic: 0x7f 0x45 0x4c 0x46 ("ELF")
Class: 64-bit
Encoding: Big-Endian
ELF version: 1
OS ABI: System V
ABI Version: 0
Type: ET_EXEC
Machine: MIPS
Version: 1
Entry Point: 0xffffffff804b0000
Program Headers Offset: 0x40
Section Headers Offset: 0x572C70
Flags: 0x808b0001
ELF Header Size: 0x40
Program Header Entry Size: 0x38
Program Header Entries: 1
Section Header Entry Size: 0x40
Section Header Entries: 0x21
.shstrtab Index: 0x20

다음과 같은 단락과 섹션이 있습니다.

_______________________________________________________________________________________________
PROGRAM HEADERS:
_______________________________________________________________________________________________
Index Type    Flags           SizeInMem  MemVirtAddress      FileOffs  SizeInFile
-----------------------------------------------------------------------------------------------
0    PT_LOAD  Write+Read+Exec 0x5AB200   0xffffffff80100000  0x4000    0x56EAC7                                           

_______________________________________________________________________________________________
SECTION HEADERS:
_______________________________________________________________________________________________
Index Name                   Type        Flags        MemVirtAddress      FileOffs  SizeInFile
-----------------------------------------------------------------------------------------------
0                            K_NULL                                  0x0       0x0       0x0
1   .text                    K_PROGBITS  Alloc+Exec   0xffffffff80100000    0x4000  0x30DFE8
2   __ex_table               K_PROGBITS  Alloc+       0xffffffff8040dff0  0x311FF0    0x5EA0
3   __dbe_table              K_PROGBITS  Alloc+       0xffffffff80413e90  0x317E90       0x0
4   .rodata                  K_PROGBITS  Alloc+       0xffffffff80414000  0x318000   0x48B68
5   .pci_fixup               K_PROGBITS  Alloc+       0xffffffff8045cb68  0x360B68     0xB20
7   __ksymtab                K_PROGBITS  Alloc+       0xffffffff8045d688  0x361688    0x8EA0
8    __ksymtab_gpl           K_PROGBITS  Alloc+       0xffffffff80466528  0x36A528    0x2580
17  __ksymtab_strings        K_PROGBITS  Alloc+       0xffffffff80468aa8  0x36CAA8    0xEBA8
18   __param                 K_PROGBITS  Alloc+       0xffffffff80477650  0x37B650     0x6E0
19  .data                    K_PROGBITS  Alloc+Write  0xffffffff80478000  0x37C000   0x2FD20
20  .data.cacheline_aligned  K_PROGBITS  Alloc+Write  0xffffffff804a8000  0x3AC000    0x7280
21  .init.text               K_PROGBITS  Alloc+Exec   0xffffffff804b0000  0x3B4000   0x31270
22  .init.data               K_PROGBITS  Alloc+Write  0xffffffff804e1270  0x3E5270    0x3708
23  .init.setup              K_PROGBITS  Alloc+Write  0xffffffff804e4980  0x3E8980     0x5B8
24  .initcall.init           K_PROGBITS  Alloc+Write  0xffffffff804e4f38  0x3E8F38     0x6D8
25  .con_initcall.init       K_PROGBITS  Alloc+Write  0xffffffff804e5610  0x3E9610      0x10
27  .exit.text               K_PROGBITS  Alloc+Exec   0xffffffff804e5620  0x3E9620    0x30C0
28  .init.ramfs              K_PROGBITS  Alloc+       0xffffffff804e9000  0x3ED000  0x185AC7
32  .shstrtab                K_STRTAB                                0x0  0x572AC7     0x1A7
6   .rio_route               K_PROGBITS  Write        0xffffffff8045d688  0x572AC7       0x0
9   __ksymtab_unused         K_PROGBITS  Write        0xffffffff80468aa8  0x572AC7       0x0
10  __ksymtab_unused_gpl     K_PROGBITS  Write        0xffffffff80468aa8  0x572AC7       0x0
11  __ksymtab_gpl_future     K_PROGBITS  Write        0xffffffff80468aa8  0x572AC7       0x0
12  __kcrctab                K_PROGBITS  Write        0xffffffff80468aa8  0x572AC7       0x0
13  __kcrctab_gpl            K_PROGBITS  Write        0xffffffff80468aa8  0x572AC7       0x0
14  __kcrctab_unused         K_PROGBITS  Write        0xffffffff80468aa8  0x572AC7       0x0
15  __kcrctab_unused_gpl     K_PROGBITS  Write        0xffffffff80468aa8  0x572AC7       0x0
16  __kcrctab_gpl_future     K_PROGBITS  Write        0xffffffff80468aa8  0x572AC7       0x0
26  .security_initcall.init  K_PROGBITS  Write        0xffffffff804e5620  0x572AC7       0x0
29  .sbss                    K_PROGBITS  Alloc+Write  0xffffffff8066f000  0x572AC7       0x0
30  .bss                     K_NOBITS    Alloc+Write  0xffffffff80670000  0x572AC7   0x3AEF0
31  .cvmx_shared_bss         K_NOBITS    Alloc+Write  0xffffffff806aaef0  0x572AC7     0x310  
_______________________________________________________________________________________________

이 ELF 파일에는 운영 체제에 필요한 파일이 포함된 1558kB init.ramfs 섹션이 내장되어 있습니다. 이 섹션은 gzip으로 압축되어 있으며 1805개의 파일과 디렉터리를 포함하는 cpio 아카이브를 포함합니다.

에 따르면: kernel.org 그리고 위키피디아, Linux 커널 cpio 추출기는 이 init.ramfs 섹션을 메모리 위치로 추출합니다.

내 질문은 다음과 같습니다

  1. cpio 아카이브 내용이 추출되는 메모리 주소는 어떻게 결정됩니까?
  2. 압축을 푼 후 커널은 특정 파일(예: /sbin/init 파일)에 대한 데이터의 메모리 주소를 어떻게 찾나요?
  3. 커널이 나중에 이러한 파일을 찾을 수 있도록 cpio 아카이브의 내용이 일종의 파일 시스템으로 추출되고 있습니까? 아니면 이러한 파일의 메모리 주소가 커널 코드에 하드 코딩되어 있습니까?

답변: 질문 1: .init.ramfs 섹션을 ELF 파일의 섹션 헤더에 지정된 0xffffffff804e9000 메모리 주소로 압축 해제할 수 없는 것 같습니다. 다음 섹션(".sbss) 앞에 여유 공간이 1560kB밖에 없기 때문입니다. ") 0xffffffff8066f000부터 메모리에 ungzip으로 압축된 cpio 아카이브는 4035kB를 차지합니다.

답변1

커널이 나중에 이러한 파일을 찾을 수 있도록 cpio 아카이브의 내용이 일종의 파일 시스템으로 추출되고 있습니까? 아니면 이러한 파일의 메모리 주소가 커널 코드에 하드 코딩되어 있습니까?

파일 시스템을 입력하십시오. 사용되는 파일 시스템 유형은 다음과 같습니다.메모리 파일 시스템, 또는임시 파일 시스템. 언급하신 링크 중 하나가 이에 대해 자세히 설명합니다.

https://github.com/torvalds/linux/blob/v4.17/Documentation/filesystems/ramfs-rootfs-initramfs.txt

ramfs와 tmpfs는 매우 유사하게 작동합니다. 이 질문에는 큰 차이가 없습니다. initramfs에서 사용하는 유형은 예를 들어 커널 버전에 따라 다를 수 있습니다(알고 싶은 경우이것을 읽어보세요). initramfs 외부에서는 일반적인 규칙은 항상 tmpfs를 사용하는 것입니다. tmpfs는 최대 공간 사용량을 제한하여 RAM 고갈과 시스템 충돌을 방지합니다.


Rootfs는 2.6 시스템에 항상 존재하는 ramfs(또는 활성화된 경우 tmpfs)의 특수 인스턴스입니다. [...]

initramfs란 무엇입니까?

모든 2.6 Linux 커널에는 커널 부팅 시 rootfs로 추출되는 gzip으로 압축된 "cpio" 형식 아카이브가 포함되어 있습니다.


Kernel.org 및 Wikipedia에 따르면 Linux 커널 cpio 추출기는 이 init.ramfs 섹션을 메모리 위치로 추출합니다. [...]

"ramfs-rootfs-initramfs.txt"의 첫 번째 부분에서 이에 대해 설명합니다.메모리 파일 시스템파일 데이터는 다음 위치에 할당됩니다.페이지 캐시, 실제 파일 시스템에서 파일 데이터를 캐시하는 데 사용되는 것과 동일한 구조입니다. ramfs 파일 페이지는 프로세스 메모리처럼 스왑 장치로 스왑될 수도 있습니다.

페이지 캐시는 커널인 최하위 할당자에 매우 가깝다고 말씀드릴 수 있습니다.페이지 할당자. 페이지 할당자는 시작 시 사용 가능한 모든 물리적 RAM 영역을 얻습니다. 여기에는 초기 커널 부분이 제외됩니다. 사용 가능한 물리적 RAM 영역은 부트로더/펌웨어에 의해 커널로 전달됩니다. 일련의 초기 라인에서 이러한 영역을 볼 수 있습니다.커널 로그, 명령에 표시된 대로 dmesg.

나중에 커널 로그에서 해제된 init.ramfs 섹션을 포함하여 더 이상 필요하지 않은 init mem에 페이지 할당자가 넘겨질 때 메시지를 볼 수 있습니다. (IIRC에는 페이지 할당자 이전에 별도의 초기 할당자가 있었지만 이는 부팅 IMO에서 가장 흥미로운 세부 사항은 아닙니다.)

2. 압축을 푼 후 커널은 특정 파일(예: /sbin/init 파일) 데이터의 메모리 주소를 어떻게 찾나요?

페이지 캐시는 인메모리 인덱스 노드(또는라고도 함)에서 연결됩니다.가상 노드. vnode는 메모리를 통해 검색됩니다.디렉토리 항목 캐시. 디렉토리 항목= 캐시의 디렉토리 항목.

ramfs란 무엇입니까?

Ramfs는 Linux의 디스크 캐싱 메커니즘(페이지 캐시 및 Dentry 캐시)을 동적으로 크기 조정 가능한 RAM 기반 파일 시스템으로 내보내는 매우 간단한 파일 시스템입니다.

일반적으로 모든 파일은 Linux에 의해 메모리에 캐시됩니다. 백업 저장소(일반적으로 파일 시스템이 마운트된 블록 장치)에서 읽은 데이터 페이지는 다시 필요할 경우를 대비해 유지되지만 가상 메모리 시스템에서 다른 용도로 메모리가 필요한 경우에는 정리(해제 가능)로 표시됩니다. 마찬가지로, 파일에 기록된 데이터는 백업 저장소에 기록되면 깨끗한 것으로 표시되지만 가상 머신이 메모리를 재할당할 때까지 캐싱 목적으로 유지됩니다. 유사한 메커니즘(카탈로그 항목 캐싱)을 사용하면 디렉토리에 대한 액세스 속도가 크게 향상됩니다.

ramfs에는 백업 저장소가 없습니다. ramfs에 기록된 파일에는 평소와 같이 디렉토리 항목과 페이지 캐시가 할당되지만 기록할 장소가 없습니다. 이는 이러한 페이지가 정리된 것으로 표시되지 않으므로 가상 머신이 메모리를 회수하려고 할 때 해제될 수 없음을 의미합니다.


답변: 질문 1: .init.ramfs 부분을 추출할 수 없는 것 같습니다.

예를 들어 페이지 할당자를 사용하여 RAM의 어느 위치에나 임시 버퍼로 압축을 풀 수 있습니다. 즉, 추출 프로세스가 스트리밍이라고 가정합니다. 즉, 유사한 접근 방식을 사용할 수 있습니다 gzip -d | cpio --extract. 이 방법을 사용하면 아카이브에서 tmpfs로 파일을 복사할 때 버퍼가 압축되지 않은 전체 cpio 아카이브를 보유할 필요가 없습니다.

관련 정보