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 섹션을 메모리 위치로 추출합니다.
내 질문은 다음과 같습니다
- cpio 아카이브 내용이 추출되는 메모리 주소는 어떻게 결정됩니까?
- 압축을 푼 후 커널은 특정 파일(예: /sbin/init 파일)에 대한 데이터의 메모리 주소를 어떻게 찾나요?
- 커널이 나중에 이러한 파일을 찾을 수 있도록 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 아카이브를 보유할 필요가 없습니다.