解决方案

解决方案

我希望找到正确的地方。我在“网络”上找不到有关我的问题的任何建议。操作系统(比如 Linux 发行版)如何从硬盘加载并将所有修改(所有应用程序)执行到 RAM 中?换句话说,我们如何使用操作系统从硬盘读取所需的数据并仅将所需的数据写入 RAM。

目的是确保操作系统(以及它执行的所有应用程序)发出的所有“指令”(这可能是错误的词)都专门写入 RAM(不会写入硬盘)。

我知道有些 Linux 发行版可以完全加载到 RAM 中,但不便之处在于我们得到的系统的大小:RAM 中没有足够的空间用于应用程序,而普通系统会从驱动器中找到所需的应用程序并将其加载到内存中。这可以通过为系统使用额外的 RAM 来实现,但与使用硬盘来保存我们需要的应用程序相比,这不是一个很好的解决方案(因为 RAM 的实际价格)

我还考虑过虚拟机,在大多数情况下,它可以读取驱动器以使用应用程序,并且只写入 RAM。但它需要从现有的已加载操作系统加载虚拟机,那么我们有没有办法跳过现有的操作系​​统部分?

如果您有任何建议或技术词汇让我自己去搜索,谢谢。

答案1

这是可能的,但并非易事。我会给你一些建议,但我无法提供详细的步骤,因为我自己从未尝试过。

  • 覆盖文件系统- 它允许您创建一个“分层”文件系统,其中下层是只读的,上层是可写的。话虽如此,下层仍然是完全可变的(您可以编辑、删除文件等,但它们并没有真正改变 - 更改完全存储在上层中),并且像一个成熟的文件系统一样工作。

  • 临时文件- 这是另一个完全驻留在内存中的成熟文件系统。您可以将容量设置为低于 RAM 量,以防止意外阻塞操作系统。此外,未使用的容量可用作常规 RAM,这很好。

  • 枢轴根/- 移动到不同目录的系统调用。

通常在启动过程的早期枢轴根被称为从早期用户空间到磁盘文件系统。您可以对此进行修改:在下层创建具有磁盘文件系统的 OverlayFS,在上层创建 tmpfs,然后将 pivot_root 设置为 OverlayFS。

请注意,上层可能会快速增长,从而消耗大量可用 RAM。可以使用 zram 来减少 RAM 使用量,但代价是 CPU 使用量,但这不是最终的解决方案。永久更新磁盘上的操作系统也会很棘手。

答案2

我将稍微扩展一下这个主题,以帮助刚开始学习这个主题的完全新手。

启动过程

第一个硬盘通常分为两个部分:

  1. 一个用于启动过程(启动计算机时读取的部分),通常/dev/sda1在大多数 Linux 发行版中调用
  2. 一个用于所有其他内容(例如系统和用户文件),名称为/dev/sdb1。(系统和用户文件可以位于不同的部分)

在引导扇区上有一个内核映像,它实际上是初始化内存文件系统图像。intramfs 是加载到 RAM 中的“最小”功能系统。它可以被视为 Linux 系统的小型版本:您将找到模块、一些您在常用系统上看到的目录,但内容不同。该小型 Linux 系统用于查看您的计算机配置(您使用的存储设备类型、您的组件是什么等),以加载您的实际系统将使用的正确模块,并找出您的实际系统文件在存储设备上的位置,以便以后可以访问。换句话说,当您启动计算机时,它会读取分区/dev/sda1并尝试找到该分区/dev/sdb1以供以后使用。但要了解如何访问您的文件,您需要了解挂载点

挂载点

在 Linux 下,所有目录都可以通过一个名为,也就是/。不要米克斯root 用户存储/root与文件系统的根目录/。当您插入外部存储设备(如 USB 驱动器)时,系统将创建一个新目录并将其用作该设备的根目录。换句话说,在该目录下,您可以访问存储在其中的所有文件。该目录称为挂载点。要创建挂载点,您需要有一个设备(例如 USB)、一个目录和一个文件系统(用作用户空间程序和设备物理内存之间的接口的程序)然后使用以下命令:

mount -t name_filesystem name_device name_directory

从技术上讲,当你插入某个东西时,你需要手动安装该设备。但是当你插入一个普通设备(比如 USB)时,Linux 会自动执行此操作。由于文件 file,计算机的所有内部设备都会在启动过程中自动安装/etc/fstab其中包含挂载它们所需的所有信息(例如硬盘驱动器的分区、CD-ROM 阅读器等)。要查看系统当前使用的所有其他挂载点,您可以查看/proc/mounts

在启动时挂载根文件系统

回到启动过程,当 initramfs 映像被加载到内存中时,它检查哪个分区硬盘驱动器的 目录用于存储文件(如/dev/sdb1),并将其挂载到文件系统的根目录下,通常称为/root。这/root与用户空间下的 目录不同/root(系统完全加载时)。在 目录下,/root您可以访问所有文件,并且/root您知道:

/root <--- initramfs
   /home
      /myName
        ... all my files
   /root <--- super user

根文件系统在启动时以只读方式挂载,然后通过虚拟文件系统(这只是处理不同设备的一种方法,因此每个设备都与不同的文件系统相关,而用户空间中的程序使用相同的命令)

Initrd 与 Initramfs

Initramfs 是 initrd 的后继者它被加载到内存中,并附带所有必要的工具,然后挂载真正的文件系统,最后从内存中卸载。但是initramfs 驻留在内存中整个系统都基于由 initramfs 挂载的根文件系统。这种差异还意味着不同的命令(例如 pivot_root成为switch_root

编辑 initramfs

用于引导过程的内核映像可以在系统中编辑。该映像存储在 上/boot。您可以通过以下方式编辑它:解压它。您要编辑的进程是init您的映像(这是执行的第一个脚本)以及实际文件系统挂载的部分,如下所示/root

log_begin_msg "Mounting root file system"
# Always load local and nfs (since these might be needed for /etc or
# /usr, irrespective of the boot script used to mount the rootfs).
. /scripts/local
. /scripts/nfs
. /scripts/${BOOT}
parse_numeric ${ROOT}
maybe_break mountroot
mount_top
mount_premount
mountroot

请注意,${ROOT}包含用于系统文件的设备名称(例如,/dev/sdb1但可以不同)

但这是一个混乱的解决方案,因为当你的系统更新镜像时(出于某些原因),你的修改将会丢失。但是 Linux 有一个解决方案,即使在更新后,也可以将你的修改保留在所有内核镜像中:initramfs 工具. 您必须进行的所有修改都将在/etc/initramfs-tools 编辑图像后使用以下命令更新内核图像:

update-initramfs -u

该映像将在下次重启后使用。因此,为了避免系统崩溃,请使用虚拟机作为虚拟盒或者

一次构建完成后,您需要将新内核与旧内核一起安装,并配置引导加载程序以使内核在引导时可选。这样,即使出现严重错误,您仍然可以使用现有内核引导系统。

覆盖

安装覆盖在现有目录上使用:

mount -t overlay -o lowerdir=/overlay/lower,upperdir=/overlay/upper,workdir=/overlay/work overlay /myDir

请注意,中间绝对没有空格,lowerdir=..,upperdir=...,workdir=... 最后一个overlay可以用 替换none(因为你没有挂载任何东西,所以没有设备在 上/myDir;你只是挂载overlay)。当你做了一些不好的事情时(如果目录不存在或者你在挂载选项中输入空格,-o ...结果将是“下面没有这样的设备/etc/fstab”(覆盖在安装过程中管理错误非常糟糕)。你可以看看关联然后寻求更多帮助。

您将在下面/myDir看到中的所有文件/overlay/lower以及您所做的所有修改(存储在中/overlay/upper):

/overlay/lower      /overlay/upper          /myDir (mountpoint)
   /file1  ---------->  /file1   --------->   /file1
      'abcdef'            'abOdef'               'abOdef'
   /file2 -------------------------------->   /file2

临时文件

tmpfs 是一种可以将 RAM 作为标准内存进行操作的文件系统。要创建 ram-disk(一块 RAM,作用类似于硬盘的一部分),请使用:

mount -t tmpfs none /myDir
           or
mount -t tmpfs tmpfs /myDir

然后,所有进行的操作/myDir都将保存到 RAM 中。

解决方案

模块

添加覆盖模块到内核​​映像(以便模块可以在启动过程中使用)。添加overlay到文件中/etc/initramfs-tools/modules

钩子

将以下脚本添加到/etc/initramfs-tools/hooks作为可执行文件

#!/bin/sh

#set kernel functions file as sources (so these functions can be used)
. /usr/share/initramfs-tools/scripts/functions
. /usr/share/initramfs-tools/hook-functions

#If you want to use a custom package into the initramfs use 
#copy_exec path_to_package
#For example if you want to use whiptail add : copy_exec /usr/bin/whiptail

脚本

将以下脚本添加到/etc/initramfs-tools/scripts/init-bottom(作为可执行文件)

#!/bin/sh

PREREQ=""
prereqs()
{
   echo "$PREREQ"
}

case $1 in
prereqs)
   prereqs
   exit 0
   ;;
esac

DIR=/overlay
UPPER_DIR=$DIR/upper
LOWER_DIR=$DIR/lower
WORK_DIR=$DIR/work

mkdir $DIR
#create temporary filesystem in RAM
mount -t tmpfs tmpfs $DIR
if [ $? -ne 0 ]; then
    fail_err "Fail to mount tmpfs on $DIR"
    exit 1
fi

#create lower, upper and workdir for overlay
mkdir $UPPER_DIR $LOWER_DIR $WORK_DIR

# move root mountpoint to the lower layer
mount -n -o move ${rootmnt} $LOWER_DIR
if [ $? -ne 0 ]; then
    fail_err "Cannot move ${rootmnt} to $LOWER_DIR"
    exit 1
fi

#mount overlay on to the root
mount -t overlay -o lowerdir=$LOWER_DIR,upperdir=$UPPER_DIR,workdir=$WORK_DIR overlay ${rootmnt}
if [ $? -ne 0 ]; then
    fail_err "Cannot mount overlay on ${rootmnt} [lowerdir=$LOWER_DIR, upperdir=$UPPER_DIR, workdir=$WORK_DIR]"
    exit 1
fi

#mount virtual filesystem over the lower dir (as it's donne for the root with /proc and /sysfs which are mounted on to the root at the end of the init)

#uncomment that section if you want to access the layers of overlay whithin userspace
#mkdir -p ${rootmnt}$DIR
#mount -n -o rbind $DIR ${rootmnt}$DIR
#if [ $? -ne 0 ]; then
#    fail_err "Cannot remount ${rootmnt} and its sub mountpoints on ${rootmnt}$DIR"
#    exit 1
#fi

# edit fstab to match the actual modifications

#get the device that is mounted on the rootfilesystem
root_device="$(awk '$2 == "/" {print $0}' ${rootmnt}/etc/fstab)"
#check if that device exists
blkid $root_device
if [ ! $? -gt 0 ]; then
    target=${rootmnt}/etc/fstab
    target_c=$target.orig
    #create a copy of the file (that will be accessible later)
    cp $target $target_c
    #remove the root device from the file
    grep -v "$root_device" $target_c > $target

    #add overlay on root as a device in the file
    awk '$2 == "'${rootmnt}'" { $2 = "/" ; print $0}' /etc/mtab >> $target
fi

更新

使用以下命令更新内核映像:update-initramfs -u

安装链接覆盖通过根文件系统

解决 raspbian SD 卡损坏问题,使用只读方式挂载根分区

自定义 Initramfs

在pivot_root之后无法卸载

将 root 挂载为 overlayfs

无法在 initrd 内挂载 overlayfs

如何使用 OverlayFS 保护根文件系统?

相关内容