AskOverflow.Dev

AskOverflow.Dev Logo AskOverflow.Dev Logo

AskOverflow.Dev Navigation

  • 主页
  • 系统&网络
  • Ubuntu
  • Unix
  • DBA
  • Computer
  • Coding
  • LangChain

Mobile menu

Close
  • 主页
  • 系统&网络
    • 最新
    • 热门
    • 标签
  • Ubuntu
    • 最新
    • 热门
    • 标签
  • Unix
    • 最新
    • 标签
  • DBA
    • 最新
    • 标签
  • Computer
    • 最新
    • 标签
  • Coding
    • 最新
    • 标签
主页 / unix / 问题 / 455003
Accepted
George Robinson
George Robinson
Asked: 2018-07-13 15:14:38 +0800 CST2018-07-13 15:14:38 +0800 CST 2018-07-13 15:14:38 +0800 CST

引导期间 initramfs gzip'ed cpio 归档的寻址方案

  • 772

以下引导文件 (vmlinux64) 适用于 Linux 内核 v2.6.21.7(发行版:Cavium-Octeon for 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

有这些段和部分:

_______________________________________________________________________________________________
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 和 Wikipedia,Linux Kernel cpio 提取器将这个 init.ramfs 部分解压缩到内存中的某个位置。

我的问题是:

  1. 是什么决定了提取 cpio 存档内容的内存地址?
  2. 提取后,内核如何找到特定文件的数据的内存地址,...例如 /sbin/init 文件?
  3. cpio 存档的内容是否被提取到某种文件系统中,允许内核稍后找到这些文件......或者这些文件的内存地址是否在内核代码中硬编码?

回复:问题 1:我不认为 .init.ramfs 部分可以解压缩到 ELF 文件的部分标题中所述的 0xffffffff804e9000 内存地址,因为在下一部分之前只有 1560kB 可用空间(“. sbss") 从内存中的 0xffffffff8066f000 开始,而 ungzip 的 cpio 存档占用 4035kB。

linux-kernel boot
  • 1 1 个回答
  • 540 Views

1 个回答

  • Voted
  1. Best Answer
    sourcejedi
    2018-07-13T15:55:25+08:002018-07-13T15:55:25+08:00

    cpio 存档的内容是否被提取到某种文件系统中,允许内核稍后找到这些文件......或者这些文件的内存地址是否在内核代码中硬编码?

    进入文件系统。使用的文件系统类型是ramfs或tmpfs。在您提到的链接之一中对此进行了详细说明。

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

    ramfs 和 tmpfs 的工作方式非常相似;这个问题没有太大区别。initramfs 使用哪种类型可能会有所不同,例如在内核版本之间(如果您需要知道,请阅读此内容)。在 initramfs 之外,一般规则是始终使用 tmpfs。tmpfs 限制最大空间使用量,以防止内存不足和系统崩溃。


    Rootfs 是 ramfs(或 tmpfs,如果已启用)的一个特殊实例,它始终存在于 2.6 系统 [...]

    什么是initramfs?

    所有 2.6 Linux 内核都包含一个 gzip 压缩的“cpio”格式存档,当内核启动时,它会被提取到 rootfs 中。


    根据:Kernel.org 和 Wikipedia,Linux 内核 cpio 提取器将这个 init.ramfs 部分解压缩到内存中的某个位置 [...]

    “ramfs-rootfs-initramfs.txt”的第一部分解释了ramfs文件数据是在页面缓存中分配的,这与用于缓存来自物理文件系统的文件数据的结构相同。ramfs 文件页面也可以换出到交换设备,就像进程内存一样。

    我可以告诉你,页面缓存非常接近最低级别的分配器,即内核页面分配器。页面分配器在启动时被交给所有可用的物理 RAM 区域;这些将排除初始内核部分。可用的物理内存区域由引导加载程序/固件传递给内核。如命令所示,您应该在内核日志早期的一系列行中看到这些区域dmesg。

    稍后在内核日志中,当页面分配器被交给不再需要的 init mem 时,您可以看到该消息,包括已释放的 init.ramfs 部分。(IIRC 在页面分配器之前有一些单独的非常早期的分配器,但这不是引导 IMO 中最令人兴奋的细节)。

    2. 解压后,内核如何找到特定文件的数据的内存地址,...例如 /sbin/init 文件?

    页面缓存从内存中的 inode 链接,也就是vnodes。通过内存中的dentry 缓存查找vnode 。 dentry = 缓存中的目录条目。

    什么是ramfs?

    Ramfs 是一个非常简单的文件系统,它将 Linux 的磁盘缓存机制(页面缓存和目录缓存)导出为基于 RAM 的可动态调整大小的文件系统。

    通常所有文件都被 Linux 缓存在内存中。从后备存储(通常是挂载文件系统的块设备)读取的数据页面会保留下来,以防再次需要它,但如果虚拟内存系统需要内存用于其他用途,则将其标记为干净(可释放)。类似地,写入文件的数据在写入后备存储后立即标记为干净,但出于缓存目的而保留,直到 VM 重新分配内存。类似的机制(dentry 缓存)极大地加快了对目录的访问。

    使用 ramfs,没有后备存储。写入 ramfs 的文件照常分配目录和页面缓存,但无处可写入。这意味着这些页面永远不会被标记为干净,因此当 VM 寻求回收内存时,它们不能被释放。


    回复:问题 1:我不认为 .init.ramfs 部分可以解压缩到

    它可以解压缩到 RAM 中任何地方的临时缓冲区,例如使用页面分配器。也就是说,我假设提取过程是流式传输的。也就是说,它可以使用与gzip -d | cpio --extract. 在将文件从存档复制到 tmpfs 时,这种方法避免了需要一个缓冲区来保存整个未压缩的 cpio 存档。

    • 1

相关问题

  • 阻止挂载系统调用

  • 为什么无线工具版本 30 成为永久测试版?

  • 程序堆栈大小

  • 哪些 802.11ac(或更高版本)WiFi 加密狗适用于 Linux 4.13 内核

  • 克隆的 SSD 无法启动并打印奇怪的线条

Sidebar

Stats

  • 问题 205573
  • 回答 270741
  • 最佳答案 135370
  • 用户 68524
  • 热门
  • 回答
  • Marko Smith

    如何将 GPG 私钥和公钥导出到文件

    • 4 个回答
  • Marko Smith

    ssh 无法协商:“找不到匹配的密码”,正在拒绝 cbc

    • 4 个回答
  • Marko Smith

    我们如何运行存储在变量中的命令?

    • 5 个回答
  • Marko Smith

    如何配置 systemd-resolved 和 systemd-networkd 以使用本地 DNS 服务器来解析本地域和远程 DNS 服务器来解析远程域?

    • 3 个回答
  • Marko Smith

    如何卸载内核模块“nvidia-drm”?

    • 13 个回答
  • Marko Smith

    dist-upgrade 后 Kali Linux 中的 apt-get update 错误 [重复]

    • 2 个回答
  • Marko Smith

    如何从 systemctl 服务日志中查看最新的 x 行

    • 5 个回答
  • Marko Smith

    Nano - 跳转到文件末尾

    • 8 个回答
  • Marko Smith

    grub 错误:你需要先加载内核

    • 4 个回答
  • Marko Smith

    如何下载软件包而不是使用 apt-get 命令安装它?

    • 7 个回答
  • Martin Hope
    rocky 如何将 GPG 私钥和公钥导出到文件 2018-11-16 05:36:15 +0800 CST
  • Martin Hope
    Wong Jia Hau ssh-add 返回:“连接代理时出错:没有这样的文件或目录” 2018-08-24 23:28:13 +0800 CST
  • Martin Hope
    Evan Carroll systemctl 状态显示:“状态:降级” 2018-06-03 18:48:17 +0800 CST
  • Martin Hope
    Tim 我们如何运行存储在变量中的命令? 2018-05-21 04:46:29 +0800 CST
  • Martin Hope
    Ankur S 为什么 /dev/null 是一个文件?为什么它的功能不作为一个简单的程序来实现? 2018-04-17 07:28:04 +0800 CST
  • Martin Hope
    user3191334 如何从 systemctl 服务日志中查看最新的 x 行 2018-02-07 00:14:16 +0800 CST
  • Martin Hope
    Marko Pacak Nano - 跳转到文件末尾 2018-02-01 01:53:03 +0800 CST
  • Martin Hope
    Kidburla 为什么真假这么大? 2018-01-26 12:14:47 +0800 CST
  • Martin Hope
    Christos Baziotis 在一个巨大的(70GB)、一行、文本文件中替换字符串 2017-12-30 06:58:33 +0800 CST
  • Martin Hope
    Bagas Sanjaya 为什么 Linux 使用 LF 作为换行符? 2017-12-20 05:48:21 +0800 CST

热门标签

linux bash debian shell-script text-processing ubuntu centos shell awk ssh

Explore

  • 主页
  • 问题
    • 最新
    • 热门
  • 标签
  • 帮助

Footer

AskOverflow.Dev

关于我们

  • 关于我们
  • 联系我们

Legal Stuff

  • Privacy Policy

Language

  • Pt
  • Server
  • Unix

© 2023 AskOverflow.DEV All Rights Reserve