Esquema de endereçamento do arquivo cpio do initramfs gzip'ed durante a inicialização

1

O seguinte arquivo de inicialização (vmlinux64) para o kernel Linux v2.6.21.7 (Distro: Cavium-Octeon para MIPS64):

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

Tem estes segmentos e seções:

_______________________________________________________________________________________________
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  
_______________________________________________________________________________________________

Observe que este arquivo ELF possui uma seção init.ramfs de 1558kB incorporada contendo arquivos essenciais para o sistema operacional. Esta seção é gzip'ed e contém um arquivo cpio com 1805 arquivos e diretórios.

De acordo com: Kernel.org e Wikipedia , o extrator de cpio do Kernel Linux descompacta esta seção init.ramfs em algum lugar na memória.

Minhas perguntas são:

  1. O que determina o endereço de memória onde o arquivo cpio conteúdo é extraído?
  2. Após a extração, como o kernel encontra os endereços de memória para os dados de um determinado arquivo, ... como o arquivo / sbin / init?
  3. O conteúdo do arquivo cpio é extraído em algum tipo de sistema de arquivos que permite ao kernel encontrar esses arquivos mais tarde ... ou os endereços de memória desses arquivos estão codificados no código do kernel?

Re: pergunta 1: Eu não acho que a seção .init.ramfs pode ser ungzip'ed para o endereço de memória 0xffffffff804e9000 indicado no cabeçalho da seção do arquivo ELF, porque há apenas 1560kB de espaço disponível lá antes da próxima seção (".sbss") começar em memória em 0xffffffff8066f000, e o arquivo cpio ungzip'ed ocupa 4035kB.

    
por George Robinson 13.07.2018 / 01:14

1 resposta

1

Are the contents of the cpio archive extracted into some kind of file system that allows the kernel to find these files later ...or are the memory addresses of these files hard-coded in the kernel's code?

Em um sistema de arquivos. O tipo de sistema de arquivos usado é ramfs , ou tmpfs . Isso é explicado em detalhes, em um dos links que você mencionou.

link

O ramfs e o tmpfs funcionam de maneira muito semelhante; Não faz muita diferença para essa questão. Qual tipo é usado para o initramfs pode variar, e. entre as versões do kernel (se você precisar saber, leia isto . Fora do initramfs, a regra geral é sempre usar o tmpfs. O tmpfs limita o uso máximo de espaço, que protege contra a falta de memória RAM e o travamento do sistema.

Rootfs is a special instance of ramfs (or tmpfs, if that's enabled), which is always present in 2.6 systems [...]

What is initramfs?

All 2.6 Linux kernels contain a gzipped "cpio" format archive, which is extracted into rootfs when the kernel boots up.

According to: Kernel.org and Wikipedia, the Linux Kernel cpio extractor unpacks this init.ramfs section somewhere in memory [...]

A primeira parte de "ramfs-rootfs-initramfs.txt" explica que os dados do arquivo ramfs estão alocados no cache de páginas , a mesma estrutura usada para armazenar dados em cache de sistemas de arquivos físicos. As páginas de arquivos do ramfs também podem ser trocadas para um dispositivo de troca, da mesma forma que a memória de processo pode.

Eu posso dizer que o cache de páginas está bem próximo do alocador de nível mais baixo, o alocador de páginas do kernel . O alocador de página recebe todas as regiões físicas de RAM disponíveis no momento da inicialização; estes irão excluir as seções iniciais do kernel. As regiões de ram físico disponíveis são passadas para o kernel pelo bootloader / firmware. Você deve ver essas regiões em uma série de linhas no início do registro do kernel , conforme mostrado pelo comando dmesg .

Posteriormente no log do kernel, você pode ver a mensagem quando o alocador de página recebe o init mem que não é mais necessário, incluindo a seção init.ramfs liberada. (IIRC há algum alocador muito cedo separado antes do alocador de página, mas esse não é o detalhe mais interessante na inicialização do IMO).

2. After extracting, how does the kernel find the memory addresses for the data of a particular file, ...such as the /sbin/init file ?

O cache de páginas está vinculado a partir dos inodes in-memory, também conhecidos como vnodes . Os vnodes são procurados através do cache dentry in-memory . dentry = entrada de diretório no cache.

What is ramfs?

Ramfs is a very simple filesystem that exports Linux's disk caching mechanisms (the page cache and dentry cache) as a dynamically resizable RAM-based filesystem.

Normally all files are cached in memory by Linux. Pages of data read from backing store (usually the block device the filesystem is mounted on) are kept around in case it's needed again, but marked as clean (freeable) in case the Virtual Memory system needs the memory for something else. Similarly, data written to files is marked clean as soon as it has been written to backing store, but kept around for caching purposes until the VM reallocates the memory. A similar mechanism (the dentry cache) greatly speeds up access to directories.

With ramfs, there is no backing store. Files written into ramfs allocate dentries and page cache as usual, but there's nowhere to write them to. This means the pages are never marked clean, so they can't be freed by the VM when it's looking to recycle memory.

Re: Question 1: I don't think the .init.ramfs section can be ungzip'ed to

Pode ser desativado para um buffer temporário em qualquer parte da RAM, por ex. usando o alocador de página. Dito isso, presumo que o processo de extração seja transmitido. Ou seja, ele pode usar uma abordagem semelhante para gzip -d | cpio --extract . Essa abordagem evita a necessidade de um buffer para armazenar todo o arquivo cpio descompactado, ao copiar os arquivos do arquivo para o tmpfs.

    
por 13.07.2018 / 01:55