[Linux] Linux 系统从启动到驱动加载

Linux 系统从启动到驱动加载

文章目录

  • Linux 系统从启动到驱动加载
    • 一、硬件上电与 BIOS/UEFI 阶段
      • 1. 1 硬件上电初始化
      • 1.2 BIOS/UEFI执行过程
      • 1.3 Bootloader加载细节
    • 二、Bootloader 阶段
    • 三、Linux 内核初始化
      • 3.1 架构相关初始化(setup_arch)
      • 3.2 核心子系统初始化
      • 3.3 虚拟文件系统(VFS)初始化
      • 3.4 内核线程创建
    • 四、驱动子系统初始化
      • 4.1 设备模型初始化(driver_init)
      • 4.2 总线子系统注册
      • 4.3 早期驱动初始化(early platform drivers)
      • 4.4 设备描述信息解析
    • 五、驱动加载与设备枚举
      • 5.1 总线驱动扫描硬件设备
      • 5.2 设备与驱动匹配
      • 5.3 驱动probe初始化
      • 5.4 创建设备节点
    • 六、用户空间初始化
      • 6.1 init 进程启动
      • 6.2 udev 设备管理
      • 6.3 驱动模块加载
      • 6.4 系统启动完成
    • 七、关键数据结构与函数
    • 八、典型驱动加载流程示例
    • 九、调试与故障排查
      • 9.1 查看内核启动日志(dmesg)
      • 9.2 检查 sysfs 设备信息(/sys/devices)
      • 9.3 使用 udevadm 监控设备事件
      • 9.4 动态加载/卸载驱动模块(insmod/rmmod)


一、硬件上电与 BIOS/UEFI 阶段

1. 1 硬件上电初始化

当计算机电源接通后:

  • 电源供应器完成自检,向主板发送Power Good信号
  • CPU从复位状态解除,寄存器被初始化为默认值(如x86架构的CS=0xF000,EIP=0xFFF0)
  • 主板时钟发生器开始工作,提供稳定的时钟信号

1.2 BIOS/UEFI执行过程

BIOS/UEFI固件执行的主要任务:

  • POST(Power-On Self Test)

    • 检测关键硬件:CPU、内存、显卡等
    • 声卡发出"滴"声表示检测通过(不同BIOS厂商的提示音编码不同)
    • 对检测到的硬件生成设备列表(如通过ACPI表)
  • 硬件初始化

    • 配置内存控制器和初始化RAM
    • 初始化基本输入输出设备(键盘、显示器)
    • 设置中断向量表(IVT)或高级中断控制器(APIC)
  • 引导设备选择

    • 按照CMOS中存储的启动顺序(如:硬盘→USB→网络)
    • 读取每个设备的引导扇区(MBR或GPT分区表的引导记录)
    • 对于UEFI系统,会查找ESP分区中的/EFI/BOOT/BOOTx64.EFI文件

1.3 Bootloader加载细节

当BIOS/UEFI找到有效启动设备后:

  • 传统BIOS会将MBR中的第一阶段引导程序(512字节)加载到内存0x7C00处
  • UEFI则直接加载EFI应用程序到内存
  • 对于GRUB2:
    • 第一阶段(boot.img)仅负责加载core.img
    • 第二阶段(core.img)包含基本文件系统驱动,用于定位/boot/grub
    • 最终加载grub.cfg配置文件并显示启动菜单

示例启动顺序:

  1. 检测到SATA硬盘
  2. 读取MBR中的引导代码
  3. 加载GRUB的stage1 → stage1.5 → stage2
  4. 显示GRUB菜单等待用户选择

二、Bootloader 阶段

  1. 引导加载器启动

    • 系统 BIOS/UEFI 完成硬件初始化后,将控制权交给存储在 MBR 或 EFI 分区中的引导加载器(如 GRUB2)
    • 常见的引导加载器包括:
      • GRUB (Grand Unified Bootloader)
      • Syslinux
      • LILO (Linux Loader)
      • systemd-boot (适用于 UEFI 系统)
  2. 内核加载过程

    • 引导加载器读取其配置文件(如 GRUB 的 grub.cfg)
    • 加载压缩的内核镜像(通常在 /boot 目录下,命名为 vmlinuz-<版本号>)到内存
    • 同时加载 initramfs(Initial RAM Filesystem)镜像
    • 典型文件示例:
      /boot/vmlinuz-5.4.0-91-generic
      /boot/initrd.img-5.4.0-91-generic
      
  3. 参数传递与内核启动

    • 引导加载器向内核传递启动参数,常见参数包括:
      • root=:指定根文件系统设备(如 root=/dev/sda1)
      • init=:指定初始化程序路径(替代默认的 /sbin/init)
      • quiet:减少启动时内核信息输出
      • splash:显示启动画面
    • 内核解压过程:
      • 首先解压缩 zImage 或 bzImage 格式的内核
      • 然后加载必要的驱动和初始化临时根文件系统
    • 最终控制权转移到内核的入口点 start_kernel() 函数(位于 init/main.c)
  4. initramfs 的作用

    • 提供早期用户空间环境
    • 包含必要的驱动程序(如磁盘控制器、文件系统驱动)
    • 挂载真正的根文件系统
    • 在嵌入式系统中可能直接作为最终根文件系统使用
  5. 特殊场景处理

    • 加密根分区:需要 initramfs 包含解密工具
    • RAID/LVM:需要加载相应的模块
    • 网络启动:需要包含网络驱动程序

三、Linux 内核初始化

3.1 架构相关初始化(setup_arch)

setup_arch() 是架构特定的初始化函数,主要负责:

  • 解析硬件信息(如通过设备树获取CPU类型、内存布局等)
  • 初始化物理内存管理(如建立memblock内存分配器)
  • 设置处理器特殊功能(如开启MMU、缓存等)
  • 架构相关的早期设备初始化(如SMP处理器初始化)

示例:在ARM架构中会初始化处理器异常向量表,x86架构则会检测和初始化ACPI。

3.2 核心子系统初始化

包括以下关键系统的初始化:

  • 页表初始化:建立内核地址空间映射,包括:
    • 内核代码段映射
    • 设备I/O空间映射
    • 早期内存分配区域映射
  • 中断控制器初始化
    • 探测并初始化本地APIC/IOAPIC(x86)
    • GIC初始化(ARM)
    • 设置中断描述符表(IDT)
  • 定时器子系统
    • 初始化高精度定时器(hrtimer)
    • 设置系统时钟源(如HPET、TSC)
    • 校准CPU频率(loops_per_jiffy)

3.3 虚拟文件系统(VFS)初始化

VFS初始化流程:

  1. 注册基础文件系统类型(如proc、sysfs、tmpfs)
  2. 初始化dentry缓存和inode缓存
  3. 挂载rootfs作为初始文件系统
  4. 创建标准文件描述符(stdin/stdout/stderr)
  5. 挂载实际根文件系统(通过root=内核参数指定)

3.4 内核线程创建

初始化的关键内核线程包括:

  • kthreadd(内核线程守护进程,pid=2)
    • 负责创建和管理其他内核线程
    • 通过kthread_create()请求创建新线程
  • 其他早期线程:
    • ksoftirqd(软中断处理线程)
    • kworker(工作队列线程)
    • migration(CPU迁移线程)
    • watchdog(看门狗监控线程)

这些初始化步骤完成后,内核将进入用户空间初始化阶段,启动第一个用户进程(通常是init或systemd)。


四、驱动子系统初始化

4.1 设备模型初始化(driver_init)

该阶段主要完成内核设备模型的核心数据结构初始化,包括:

  • kobject 子系统初始化,建立设备层次结构基础
  • 设备类和属性文件系统的创建(/sys/class/)
  • 内核对象引用计数机制的建立
  • 设备号分配器的初始化(devtmpfs)

4.2 总线子系统注册

分平台总线类型进行初始化:

  • platform_bus_init

    • 注册平台总线类型(platform_bus_type)
    • 初始化 platform_device 和 platform_driver 的匹配机制
    • 创建/sys/bus/platform/目录结构
    • 典型应用场景:SoC内置设备(如GPIO控制器、时钟模块)
  • pci_init

    • PCI总线探测和枚举
    • PCI设备资源分配(IO空间、内存空间)
    • 建立PCI设备树结构
    • PCI设备驱动匹配机制初始化

4.3 早期驱动初始化(early platform drivers)

在基本设备模型建立后立即加载的关键驱动:

  • 内存控制器驱动
  • 串口调试驱动(earlycon)
  • 时钟源驱动
  • 中断控制器驱动
    这些驱动通过early_platform_init机制注册,具有以下特性:
  • 在常规驱动加载前完成初始化
  • 使用简化版的资源获取接口
  • 通常通过命令行参数指定(如earlycon=uart8250,mmio,0xfe001000

4.4 设备描述信息解析

根据系统类型采用不同配置机制:

设备树(DT)系统

  • 解析/boot/dtb文件或U-Boot传递的设备树
  • 展开设备树节点为device_node结构
  • 将设备树节点转换为platform_device
  • 处理设备树中的中断映射、DMA范围等特殊属性

ACPI系统

  • 解析ACPI表(DSDT、SSDT等)
  • 转换ACPI设备为平台设备
  • 处理_PRT(中断路由)、_CRS(资源分配)等方法
  • 支持ACPI电源管理扩展功能

两种系统最终都会生成统一的设备资源描述,包括:

  • 内存映射区域
  • 中断号
  • DMA通道
  • 时钟源
  • 电源管理参数

五、驱动加载与设备枚举

5.1 总线驱动扫描硬件设备

总线驱动负责识别和扫描连接的硬件设备。常见方式包括:

  • PCI设备枚举:通过读取PCI配置空间(Configuration Space)获取设备Vendor ID、Device ID等信息
  • 设备树解析(DT node parsing):在ARM架构中解析设备树(Device Tree)的节点信息
  • ACPI枚举:x86架构通过ACPI表获取设备信息
  • USB总线枚举:通过USB协议发现连接的设备

示例:PCI枚举过程中会遍历所有总线号码(bus number),对每个设备/功能组合读取其配置寄存器。

5.2 设备与驱动匹配

内核通过driver_match_device()函数进行匹配,主要依据:

  • 设备树中的compatible属性
  • ACPI设备ID(HID/UID/CID)
  • PCI设备的Vendor/Device ID
  • 平台设备的名称匹配

匹配优先级通常为:设备树匹配 > ACPI匹配 > ID表格匹配 > 名称匹配。

5.3 驱动probe初始化

匹配成功后调用驱动的probe()函数进行:

  1. 资源分配(内存、IRQ、DMA等)
  2. 硬件初始化(寄存器配置、固件加载)
  3. 设备特定设置(时钟、电源管理)
  4. 子系统注册(如输入设备、网络设备等)

典型错误处理包括:检查资源可用性、逐步回滚失败操作。

5.4 创建设备节点

通过devtmpfs自动创建设备文件:

  • 内核调用device_add()将设备注册到系统
  • 根据设备类型(字符/块设备)创建/dev节点
  • 设置正确的设备号(major/minor)
  • 应用层可通过udev/mdev规则进一步配置节点属性

特殊设备可能还需要:

  • sysfs属性文件(/sys/class/...
  • debugfs接口
  • 用户空间通知机制(uevent)

六、用户空间初始化

6.1 init 进程启动

内核最后阶段会启动第一个用户空间进程 init(PID=1),根据系统配置选用不同的 init 系统:

  • systemd(现代主流发行版):采用并行化的服务启动方式,提供单元(unit)管理
    • 读取 /etc/systemd/system//usr/lib/systemd/system/ 下的单元文件
    • 启动基础目标(target)如 multi-user.targetgraphical.target
  • sysvinit(传统系统):串行执行 /etc/init.d/ 中的启动脚本
    • 通过运行级别(runlevel)控制启动阶段
    • 典型流程:先挂载文件系统,再启动基础服务

6.2 udev 设备管理

udev 守护进程负责动态设备管理:

  • 监听内核通过 netlink 发送的 uevent
  • 处理设备热插拔事件(如 USB 插入)
  • 根据 /etc/udev/rules.d/ 规则文件:
    • 创建设备节点(如 /dev/sda1
    • 设置设备权限和所有者
    • 触发关联的硬件初始化脚本

6.3 驱动模块加载

通过 modprobe 机制加载用户态驱动模块:

  • 读取 /etc/modprobe.d/ 配置文件
  • 自动解决模块依赖关系
  • 典型应用场景:
    • 加载文件系统驱动(如 ext4、ntfs)
    • 加载特殊硬件驱动(如 NVIDIA 显卡)
    • 加载网络协议栈模块

6.4 系统启动完成

完成所有初始化步骤后:

  • 启动登录管理器(如 gdm、lightdm)进入图形界面
  • 或显示文本登录提示符(tty1-6)
  • 记录启动日志到 /var/log/boot.log
  • 系统进入多用户模式,所有服务正常运行

七、关键数据结构与函数

Linux设备驱动模型中的两个核心数据结构及其关系:

/*** struct device_driver - 驱动对象的基本表示* @name: 驱动名称,用于sysfs显示和模块匹配* @bus: 指向驱动所属的总线类型,如platform_bus_type* @probe: 驱动探测回调函数,当设备与驱动匹配时调用* * 示例:当注册i2c_driver时,需要设置这些字段*/
struct device_driver {const char *name;struct bus_type *bus;int (*probe)(struct device *dev);
};/*** struct bus_type - 总线类型的抽象表示* @name: 总线名称,如"platform"、"pci"等* @match: 总线匹配函数,用于判断设备和驱动是否兼容* * 总线负责管理其下的设备和驱动,典型的匹配过程:* 1. 设备注册时,总线遍历所有驱动,调用match函数* 2. 驱动注册时,总线遍历所有设备,调用match函数* 3. 匹配成功则调用驱动的probe函数*/
struct bus_type {char *name;int (*match)(struct device *dev, struct device_driver *drv);
};

工作流程说明:

  1. 系统初始化时会注册各种总线类型(platform/pci/i2c等)
  2. 驱动开发者编写驱动时:
    • 定义device_driver结构体实例
    • 实现probe函数进行设备初始化
    • 向总线注册该驱动
  3. 当匹配发生时,总线层会:
    • 通过match函数验证设备和驱动的兼容性
    • 调用驱动的probe函数初始化设备
    • 建立sysfs中的设备-驱动关联

八、典型驱动加载流程示例

以下是一个完整的 PCI 设备驱动加载流程示例,展示了从驱动注册到设备初始化的关键步骤:

// 1. 定义设备ID表,用于匹配支持的PCI设备
static const struct pci_device_id my_pci_ids[] = {{ PCI_DEVICE(0x10AB, 0x1100), .driver_data = 0 },  // 厂商ID 0x10AB,设备ID 0x1100{ PCI_DEVICE(0x10AB, 0x1200), .driver_data = 0 },  // 另一个兼容设备{ 0, }  // 结束标记
};// 2. 定义驱动操作函数
static int my_probe(struct pci_dev *pdev, const struct pci_device_id *id)
{int retval;// 使能PCI设备retval = pci_enable_device(pdev);if (retval) {dev_err(&pdev->dev, "Failed to enable PCI device\n");return retval;}// 获取设备资源(如内存区域、中断号等)// ...具体设备初始化代码...dev_info(&pdev->dev, "Device successfully initialized\n");return 0;
}static void my_remove(struct pci_dev *pdev)
{// 释放资源,关闭设备// ...清理代码...pci_disable_device(pdev);dev_info(&pdev->dev, "Device removed\n");
}// 3. 定义PCI驱动结构体
static struct pci_driver my_driver = {.name     = "my_device",      // 驱动名称.id_table = my_pci_ids,       // 设备匹配表.probe    = my_probe,         // 设备发现时的回调.remove   = my_remove,        // 设备移除时的回调// 可选:.suspend/.resume 等电源管理回调
};// 4. 注册PCI驱动
module_pci_driver(my_driver);// 5. 模块信息
MODULE_DEVICE_TABLE(pci, my_pci_ids);
MODULE_LICENSE("GPL");
MODULE_AUTHOR("Your Name");
MODULE_DESCRIPTION("Sample PCI Device Driver");

典型工作流程:

  1. 内核加载驱动模块时调用module_pci_driver宏注册驱动
  2. 内核遍历PCI总线,将每个设备与id_table进行匹配
  3. 找到匹配设备后,调用probe函数初始化设备
  4. 设备使用期间可能触发中断/处理请求
  5. 设备移除或模块卸载时调用remove函数清理资源

注意事项:

  • 必须实现基本的probe/remove函数对
  • 需要正确处理设备使能/禁用流程
  • 建议添加适当的错误处理和资源管理
  • 现代驱动通常还需要实现电源管理回调

九、调试与故障排查

9.1 查看内核启动日志(dmesg)

dmesg命令是排查驱动程序问题的首选工具,它显示内核环形缓冲区中的消息。典型使用场景包括:

  • 查看驱动加载时的初始化信息:dmesg | grep <驱动模块名>
  • 跟踪设备插拔事件:dmesg -w(实时监控)
  • 检查错误信息:dmesg --level=err,warn
  • 清空缓冲区:dmesg -c(需要root权限)

9.2 检查 sysfs 设备信息(/sys/devices)

sysfs文件系统提供了设备树的详细信息:

/sys/devices/
├── platform
│   └── <设备名>/
│       ├── driver -> ../../../bus/platform/drivers/<驱动名>
│       ├── modalias
│       └── power/

重要检查项:

  • 设备是否被正确识别:ls /sys/bus/<总线类型>/devices
  • 驱动绑定状态:查看设备目录下的driver符号链接
  • 设备参数:如/sys/class/gpio/gpio<N>/下的各种属性文件

9.3 使用 udevadm 监控设备事件

udev工具链的典型应用:

# 监控所有设备事件
udevadm monitor# 查看特定设备属性
udevadm info -a -p /sys/class/net/eth0# 触发设备重扫描
udevadm trigger

关键调试场景:

  • 检查规则匹配:udevadm test /sys/class/<设备类>/<设备名>
  • 验证热插拔事件处理
  • 调试udev规则执行过程

9.4 动态加载/卸载驱动模块(insmod/rmmod)

驱动模块管理操作流程:

# 加载模块(需.ko文件路径)
sudo insmod module.ko [参数名=参数值]# 查看已加载模块
lsmod | grep <模块名># 卸载模块(需确保无设备在使用)
sudo rmmod module# 更常用的modprobe工具
sudo modprobe module_name
sudo modprobe -r module_name

注意事项:

  • 模块参数可以通过/sys/module/<模块名>/parameters/查看或修改
  • 依赖关系处理:modprobe会自动解决依赖
  • 查看模块信息:modinfo <模块名>
  • 常见错误:模块版本不匹配、符号未导出、资源冲突等

研究学习不易,点赞易。
工作生活不易,收藏易,点收藏不迷茫 :)


本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.pswp.cn/diannao/85470.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Spring Boot DevTools 热部署

在Spring Boot项目中加入 spring-boot-devtools 热部署依赖启动器后&#xff0c;通常不需要手动重启项目即可让更改生效。spring-boot-devtools 的核心特性之一就是自动重启或热加载。 Spring Boot DevTools 热部署关键知识点 &#x1f525; 目的&#xff1a;spring-boot-devt…

uni-app学习笔记十五-vue3页面生命周期(二)

onShow&#xff1a;用于监听页面显示&#xff0c;页面每次出现在屏幕上都触发&#xff0c;包括从下级页面点返回露出当前页面&#xff1b; onHide:监听页面隐藏&#xff0c;当离开当前页面时触发。 示例代码&#xff1a; <template><view>姓名&#xff1a;{{nam…

LIKE ‘%xxx%‘ 和 LIKE ‘xxx%‘ 的索引影响分析

LIKE ‘%xxx%’ 和 LIKE ‘xxx%’ 的索引影响分析 一、基础概念解析 1.1 LIKE操作符的工作原理 LIKE是SQL中用于模式匹配的操作符,支持两种通配符: %:匹配任意数量字符(包括零个字符)_:匹配单个字符go专栏:https://duoke360.com/tutorial/path/golang 1.2 数据库索引…

【软件测试】测试框架(unittest/pytest)

本文介绍了Python 中最常用的两个测试框架&#xff1a;unittest 和 pytest&#xff0c;帮助你编写更规范、可维护的自动化测试用例。 一、unittest 框架 unittest 是 Python 内置的标准库&#xff0c;无需额外安装&#xff0c;适合初学者入门。它借鉴了 JUnit 的设计理念&…

麒麟信安安装谷歌浏览器

参考文档 麒麟信安系统Chrome离线安装包&#xff1a;高效便捷的浏览器解决方案-CSDN博客 项目文件预览 - 麒麟信安系统Chrome离线安装包:本仓库提供了一个适用于麒麟信安系统的Chrome浏览器离线安装包。该安装包包含了所有必要的依赖文件&#xff0c;并且已经对系统中已有的依…

Wireshark 使用教程:让抓包不再神秘

一、什么是 tshark&#xff1f; tshark 是 Wireshark 的命令行版本&#xff0c;支持几乎所有 Wireshark 的核心功能。它可以用来&#xff1a; 抓包并保存为 pcap 文件 实时显示数据包信息 提取指定字段进行分析 配合 shell 脚本完成自动化任务 二、安装与验证 Kali Linux…

从0到1:多医院陪诊小程序开发笔记(上)

概要设计 医院陪诊预约小程序&#xff1a;随着移动互联网的普及&#xff0c;越来越多的医院陪诊服务开始向线上转型, 传统的预约方式往往效率低下&#xff0c;用户需耗费大量时间进行电话预约或现场排队&#xff0c;陪诊服务预约小程序集多种服务于一体&#xff0c;可以提高服…

定时任务:springboot集成xxl-job-core(二)

定时任务实现方式&#xff1a; 存在的问题&#xff1a; xxl-job的原理&#xff1a; 可以根据服务器的个数进行动态分片&#xff0c;每台服务器分到的处理数据是不一样的。 1. 多台机器动态注册 多台机器同时配置了调度器xxl-job-admin之后&#xff0c;执行器那里会有多个注…

Unity使用Lua框架和C#框架开发游戏的区别

在Unity中使用Lua框架和C#框架开发游戏有显著的区别&#xff0c;主要体现在性能、开发效率、热更新能力、维护成本等方面。 1. 语言类型与设计目标 维度LuaC#类型动态类型、解释型脚本语言静态类型、编译型面向对象语言设计初衷轻量级嵌入、配置和扩展宿主程序通用开发&#…

高精度文档解析利器:Mistral OCR 全面解析与技术应用

目录 &#x1f680; 高精度文档解析利器&#xff1a;Mistral OCR 全面解析与技术应用 一、什么是 Mistral OCR&#xff1f; 二、Mistral OCR 的核心特点 ✅ 1. 支持复杂文档结构解析 ✅ 2. 高识别精度 ✅ 3. 与 AI 系统深度集成 ✅ 4. 可扩展性与容错能力 三、技术原理…

腾讯云开发者社区文章内容提取免费API接口教程

接口简介&#xff1a; 提取指定腾讯云开发者社区文章内容。本接口仅做内容提取&#xff0c;未经作者授权请勿转载。 请求地址&#xff1a; https://cn.apihz.cn/api/caiji/tencent.php 请求方式&#xff1a; POST或GET。 请求参数&#xff1a; 【名称】【参数】【必填】【说…

【项目】在线OJ(负载均衡式)

目录 一、项目目标 二、开发环境 1.技术栈 2.开发环境 三、项目树 目录结构 功能逻辑 编写思路 四、编码 1.complie_server 服务功能 代码蓝图 开发编译功能 日志功能 ​编辑 测试编译模块 开发运行功能 设置运行限制 jsoncpp 编写CR 如何生成唯一文件名 …

【后端高阶面经:架构篇】50、数据存储架构:如何改善系统的数据存储能力?

一、数据存储架构设计核心原则 (一)分层存储架构:让数据各得其所 根据数据访问频率和价值,将数据划分为热、温、冷三层,匹配不同存储介质,实现性能与成本的平衡。 热数据层:访问频率>100次/秒。采用Redis集群存储高频访问数据(如用户登录态、实时交易数据),配合…

B1、进度汇报(— 25/05/31)

本文档汇总了各成员在 2025 年 5 月 11 日 ~ 5 月 31 日完成的工作。我们遇到了进度问题&#xff08;收工后需反思&#xff09;&#xff1a; 本学期第十四周&#xff08;05/19 ~ 05/25&#xff09;有相当多课程需要提交实验结果或上台展示。本学期第十六周&#xff08;06/02 ~…

每天总结一个html标签——a标签

文章目录 一、定义与使用说明二、支持的属性三、支持的事件四、默认样式五、常见用法1. 文本链接2. 图片链接3. 导航栏 在前端开发中&#xff0c;a标签&#xff08;锚点标签&#xff09;是最常用的HTML标签之一&#xff0c;主要用于创建超链接&#xff0c;实现页面间的跳转或下…

云服务器突发宕机或无响应怎么办

当云服务器突发宕机或无响应时&#xff0c;需快速定位问题并恢复服务。以下是分步骤的解决方案&#xff1a; 1. 初步确认问题 检查网络连接 本地网络是否正常&#xff1f;尝试 ping 其他网站 排除本地问题。 使用 ping <服务器IP> 或 traceroute <IP> 测试网络连通…

动态IP与区块链:重构网络信任的底层革命

在数字经济蓬勃发展的今天&#xff0c;网络安全与数据隐私正面临前所未有的挑战。动态IP技术与区块链的深度融合&#xff0c;正在构建一个去中心化、高可信的网络基础设施&#xff0c;为Web3.0时代的到来奠定基础。 一、技术碰撞&#xff1a;动态IP与区块链的天然契合 动态I…

从0开始学vue:vue3和vue2的关系

一、版本演进关系1. 继承关系2. 版本生命周期 二、核心差异对比三、关键演进方向1. Composition API2. 性能优化 四、迁移策略1. 兼容构建模式2. 关键破坏性变更 五、生态演进1. 官方库升级2. 构建工具链 六、选型建议1. 新项目2. 现有项目 七、未来展望 一、版本演进关系 1. …

Vue 核心技术与实战智慧商城项目Day08-10

温馨提示&#xff1a;这个黑马的视频在b占可以找到&#xff0c;里面有完整的教学过程 然后这个项目有完整的代码&#xff0c;我已经上传了&#xff0c;如果审核成功大家就可以看了&#xff0c;但是需要审核多久我也不是很确定 1.项目演示 2. 项目收获 3. 创建项目 4. 调整初始化…

AR/MR实时光照阴影开发教程

一、效果演示 1、PICO4 Ultra MR 发光的球 2、AR实时光照 二、实现原理 PICO4 Ultra MR开发时&#xff0c;通过空间网格能力扫描周围环境&#xff0c;然后将扫描到的环境网格材质替换为一个透明材质并停止扫描&#xff1b;基于Google ARCore XR Plugin和ARFoundation进行安卓手…