当前位置: 首页 > news >正文

阅读网站模板公司网址有哪些

阅读网站模板,公司网址有哪些,上海高端网站建设服务公司,网站相互推广怎么做系列文章目录 Linux内核学习 Linux 知识(1) Linux 知识(2) WSL Ubuntu QEMU 虚拟机 Linux 调试视频 PCIe 与 USB 的补充知识 vscode 使用说明 树莓派 4B 指南 设备驱动畅想 Linux内核子系统 Linux 文件系统挂载 文章目录 系列文章…

在这里插入图片描述

系列文章目录


Linux内核学习
Linux 知识(1)
Linux 知识(2)
WSL Ubuntu
QEMU 虚拟机
Linux 调试视频
PCIe 与 USB 的补充知识
vscode 使用说明
树莓派 4B 指南
设备驱动畅想
Linux内核子系统
Linux 文件系统挂载


文章目录

  • 系列文章目录
  • 1. initrd 阶段的用户空间初始化脚本执行
    • 1.1 解压缩并挂载 initrd 文件系统
    • 1.2 加载介质驱动的机制
  • 2. 挂载真实文件系统后的用户空间初始化脚本执行
    • 2.1 挂载真实文件系统
  • 3. 执行用户空间初始化脚本
    • 3.1 内核中执行用户空间初始化脚本
    • 3.2 用户空间初始化脚本
  • 4. 加载默认模块
    • 4.1 Linux 6.12.5 替代方案 ?
  • 5. 总结


1. initrd 阶段的用户空间初始化脚本执行

initrd 阶段,内核会解压缩并挂载 initrd 文件系统。

1.1 解压缩并挂载 initrd 文件系统

populate_rootfs 函数负责解压缩 initrd 并将其挂载为根文件系统。以下是相关代码:

// init/initramfs.c
static int __init populate_rootfs(void)
{char *err = unpack_to_rootfs(__initramfs_start, __initramfs_size);if (err)panic("%s", err); /* Failed to decompress INTERNAL initramfs */if (initrd_start) {
#ifdef CONFIG_BLK_DEV_RAMint fd;printk(KERN_INFO "Trying to unpack rootfs image as initramfs...\n");err = unpack_to_rootfs((char *)initrd_start, initrd_end - initrd_start);if (!err) {free_initrd();goto done;} else {clean_rootfs();unpack_to_rootfs(__initramfs_start, __initramfs_size);}printk(KERN_INFO "rootfs image is not initramfs (%s); looks like an initrd\n", err);fd = sys_open("/initrd.image", O_WRONLY | O_CREAT, 0700);if (fd >= 0) {sys_write(fd, (char *)initrd_start, initrd_end - initrd_start);sys_close(fd);free_initrd();}done:
#elseprintk(KERN_INFO "Unpacking initramfs...\n");err = unpack_to_rootfs((char *)initrd_start, initrd_end - initrd_start);if (err)printk(KERN_EMERG "Initramfs unpacking failed: %s\n", err);free_initrd();
#endif/** Try loading default modules from initramfs. This gives* us a chance to load before device_initcalls.*/load_default_modules();}return 0;
}
rootfs_initcall(populate_rootfs);

1.2 加载介质驱动的机制

initrd 阶段,内核会通过以下机制加载相关的介质驱动:

  1. 检测根文件系统所在的设备:

    • 内核会根据 saved_root_name 变量来确定根文件系统所在的设备。这个变量通常由引导加载程序(如 GRUB)传递给内核。
  2. 加载默认模块:

    • initrd 阶段,内核会尝试加载默认的内核模块,这些模块通常包括识别和访问根文件系统所在介质所需的驱动程序。
    • 这些模块可以通过 initrd 文件系统中的 /linuxrc/init 脚本加载,也可以通过内核的 load_default_modules 函数加载。
  3. 等待设备探测完成:

    • 内核会等待根文件系统所在的设备完成探测,以确保设备驱动程序已经加载并准备好使用。

2. 挂载真实文件系统后的用户空间初始化脚本执行

在挂载真实文件系统后,内核会切换到真实文件系统,并执行用户空间的初始化脚本。这个过程主要发生在 prepare_namespace 函数之后。

2.1 挂载真实文件系统

prepare_namespace 函数负责挂载真实文件系统。以下是相关代码:

// fs/namespace.c
void __init prepare_namespace(void)
{int is_floppy;if (root_delay) {printk(KERN_INFO "Waiting %d sec before mounting root device...\n",root_delay);ssleep(root_delay);}wait_for_device_probe();if (saved_root_name[0]) {root_device_name = saved_root_name;if (!strncmp(root_device_name, "mtd", 3) ||!strncmp(root_device_name, "ubi", 3)) {mount_block_root(root_device_name, root_mountflags);goto out;}ROOT_DEV = name_to_dev_t(root_device_name);if (strncmp(root_device_name, "/dev/", 5) == 0)root_device_name += 5;}if (initrd_load())goto out;if ((ROOT_DEV == 0) && root_wait) {printk(KERN_INFO "Waiting for root device %s...\n",saved_root_name);while (driver_probe_done() != 0 ||(ROOT_DEV = name_to_dev_t(saved_root_name)) == 0)msleep(100);async_synchronize_full();}is_floppy = MAJOR(ROOT_DEV) == FLOPPY_MAJOR;if (is_floppy && rd_doload && rd_load_disk(0))ROOT_DEV = Root_RAM0;mount_root();
out:devtmpfs_mount("dev");sys_mount(".", "/", NULL, MS_MOVE, NULL);sys_chroot(".");
}

3. 执行用户空间初始化脚本

3.1 内核中执行用户空间初始化脚本

prepare_namespace 函数之后,内核会执行用户空间的初始化脚本。这是通过 kernel_init 函数实现的。以下是相关代码:

// init/main.c
static noinline void __init kernel_init_freeable(void)
{wait_for_completion(&kthreadd_done);gfp_allowed_mask = __GFP_BITS_MASK;set_mems_allowed(node_states[N_MEMORY]);set_cpus_allowed_ptr(current, cpu_all_mask);cad_pid = task_pid(current);smp_prepare_cpus(setup_max_cpus);do_pre_smp_initcalls();lockup_detector_init();smp_init();sched_init_smp();do_basic_setup();if (sys_open((const char __user *) "/dev/console", O_RDWR, 0) < 0)pr_err("Warning: unable to open an initial console.\n");(void) sys_dup(0);(void) sys_dup(0);if (!ramdisk_execute_command)ramdisk_execute_command = "/init";if (sys_access((const char __user *) ramdisk_execute_command, 0) != 0) {ramdisk_execute_command = NULL;prepare_namespace();}load_default_modules();if (ramdisk_execute_command) {run_init_process(ramdisk_execute_command);} else {run_init_process("/sbin/init");}
}

在上述代码中,kernel_init_freeable 函数会检查是否存在用户空间的初始化脚本(如 /linuxrc/init),如果存在,则通过 run_init_process 函数执行该脚本。

3.2 用户空间初始化脚本

用户空间的初始化脚本(如 /linuxrc/init)会在切换到真实文件系统后执行。以下是相关代码:

#!/bin/sh
# /linuxrc# 加载必要的驱动模块
modprobe usb-storage
modprobe scsi_mod
modprobe ext4# 挂载真实文件系统
mount -a# 切换到真实根文件系统
pivot_root /mnt /dev/null
exec switch_root /sbin/init

在上述脚本中,modprobe 命令会加载必要的驱动模块,以便挂载真实文件系统。

4. 加载默认模块

initrd 阶段,内核会通过 load_default_modules 函数加载默认的内核模块。这些模块通常包括识别和访问根文件系统所在介质所需的驱动程序。

void __init load_default_modules(void)
{struct module *mod;int err;for_each_module(mod) {if (mod->state == MOD_STATE_LIVE) {err = try_to_load_module(mod->name);if (err)printk(KERN_ERR "Failed to load module %s\n", mod->name);}}
}

pivot_root linux,initrd如何切入linux文件系统

在 Linux 内核中,load_default_modules 函数的主要功能是在系统启动过程中加载一组默认的内核模块,这些模块对于系统的正常运行至关重要。以下是该函数的详细功能说明:

  1. 加载默认模块
    load_default_modules 函数负责加载系统启动时所需的一组默认内核模块。这些模块通常包括设备驱动程序、文件系统支持模块以及其他系统服务模块。
  2. 模块初始化
    在内核启动过程中,需要初始化各种组件和驱动程序。load_default_modules 函数通过加载必要的模块来确保系统具备所需的驱动和功能,从而保证系统能够正常运行。
  3. 依赖关系处理
    内核模块之间可能存在依赖关系。load_default_modules 函数确保这些依赖关系得到正确处理,模块按照正确的顺序加载。这对于系统的稳定性和功能性至关重要。
  4. 配置文件支持
    该函数还会加载由系统配置文件指定的模块。这些配置文件通常位于 /etc/modules-load.d/ 目录下,每个文件包含一个或多个模块名称,系统启动时会自动加载这些模块。
  5. 内核引导参数支持
    除了配置文件,load_default_modules 函数还会处理通过内核引导参数指定的模块加载。例如,使用 modules_loadrd.modules_load 参数可以在启动时加载特定的模块。
  6. 自动模块加载
    对于大多数硬件设备,Linux 内核会自动检测并加载相应的驱动模块。load_default_modules 函数通过使用存储在 /lib/modules/VERSION/modules.alias 中的数据库来实现这一点,该数据库包含了模块与硬件设备之间的映射关系。
  7. 手动模块加载
    如果需要手动加载某个模块,可以使用 modprobe 命令。该命令会根据模块的依赖关系加载所需的模块,并将其添加到内核中。
  8. 模块验证
    在加载模块时,load_default_modules 函数还会执行一些验证操作,确保模块的完整性和兼容性。这包括检查模块的签名和验证 ELF 文件的合法性。
  9. 模块初始化函数调用
    该函数还会调用模块的初始化函数,这些函数通常使用 module_init 宏进行声明。这些初始化函数负责设置模块的运行环境,使其准备好供系统使用。

load_default_modules 函数在 Linux 内核启动过程中扮演着重要角色,通过加载默认的内核模块,确保系统具备所需的驱动和功能。它不仅处理模块之间的依赖关系,还支持通过配置文件和内核引导参数加载特定模块,从而保证系统的正常运行和硬件设备的正常工作。

4.1 Linux 6.12.5 替代方案 ?

在 Linux 6.12.5 内核中,确实没有 load_default_modules 函数。其替代实现主要通过 systemd-modules-load 服务来完成,该服务在系统启动时自动加载内核模块。

5. 总结

  1. 虚拟根文件系统中没有 /init
    initrd 阶段,如果虚拟根文件系统中没有 /init 文件,则会执行 prepare_namespace 函数来挂载真实根文件系统。为了识别根文件系统所在的介质(如 SD、SCSI 等),内核会通过 load_default_modules 函数加载相关的介质驱动。这些驱动程序确保内核能够正确识别和访问根文件系统所在的设备。

  2. 虚拟根文件系统中有 /init
    initrd 阶段,如果虚拟根文件系统中有 /init 文件,则不执行 prepare_namespace 函数来挂载真实根文件系统,真实根文件系统挂载将在 /init 脚本中进行。代码示例如下:

#!/bin/sh
# /linuxrc# 加载必要的驱动模块
modprobe usb-storage
modprobe scsi_mod
modprobe ext4# 挂载真实文件系统
mount -a# 切换到真实根文件系统
pivot_root /mnt /dev/null
exec switch_root /sbin/init

initrd 典型的系统启动顺序

  1. boot loader加载内核并初始化ram disk

  2. 内核把initrd转化成正常的ram disk并释放initrd使用的内存

  3. initrd作为root被挂载,赋予读写权限。

  4. /linuxrc被执行(这可以是任何可执行文件,如脚本,运行在uid 0,可以做任何初始化)。

  5. linuxrc挂载真正的根文件系统

  6. linuxrc使用pivot_root系统调用把根文件系统放在根目录。

  7. 正常的启动序列(/sbin/init)在根文件系统上执行。

  8. initrd文件系统被移去。


   
 

http://www.mmbaike.com/news/40060.html

相关文章:

  • 佛山网站建设费用预算哪里有培训班
  • 网站开发模板word完整html网页代码案例
  • 左右网站模版沈阳网站制作公司
  • 网站开发提高加载速度营销型网站建设托管
  • 嵌入式开发培训班费用大概多少黑帽seo是作弊手法
  • 一流的龙岗网站设计seo诊断方案
  • 网站seo优化怎么做百度企业
  • 怎样做号网站优化seo推广编辑
  • 什么网站做视频新闻内容摘抄
  • 东莞人才市场招聘官网网站如何做seo排名
  • 武汉做网站排名百度搜索排行榜
  • 南宁哪里有seo推广厂家网站排名seo软件
  • 网站备案ip查询竞价托管外包费用
  • 网站开发 动易网站推广如何引流
  • 河北邯郸房价青岛seo网络推广
  • 我们的爱情网站制作百度官方网站下载
  • 网站布局设计排版网络运营推广是做什么的
  • 网站内容页怎么做的网站免费推广
  • 我和你99谁做的网站怎样在百度上做免费推广
  • 华人黄网站大全游戏代理免费加盟
  • 一键建站系统源码关键词查网站
  • 网站项目验收广告策划案优秀案例
  • 广州网站建设建航2022年新闻摘抄十条
  • 微网站特效百度域名查询官网
  • 室内设计培训学费自己做seo网站推广
  • 小米4路由器可以做网站嘛新闻稿在线
  • 购买备案域名山西网络营销seo
  • 中文网站建设计划书推广软文怎么写
  • 罗玉凤做网站链接生成二维码
  • 四川省建设网站平台百度页面