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

嵌入式知识点总结 Linux驱动 (五)-linux内核

针对于嵌入式软件杂乱的知识点总结起来,提供给读者学习复习对下述内容的强化。

目录

1.内核镜像格式有几种?分别有什么区别?

2.内核中申请内存有哪几个函数?有什么区别?

3.什么是内核空间,用户空间?

4.为什么需要区分内核空间与用户空间?

5.什么是内核态和用户态?

6.用户空间与内核通信方式有哪些?

7.内核链表为什么具有通用性?

8.应用程序中open()在linux中执行过程中是如何从用户空间到内核空间?

9.怎么申请大块内核内存?


1.内核镜像格式有几种?分别有什么区别?

1. zImage

描述

zImage 是一种压缩的内核镜像格式,适用于大多数嵌入式系统和x86架构。

它是通过将内核镜像压缩后,加上解压缩代码生成的。

特点

压缩格式,体积较小。

适用于内存有限的嵌入式系统。

通常用于传统的BIOS引导方式。

适用场景

嵌入式Linux系统。

旧版x86系统。

2. bzImage

描述

bzImage 是 zImage 的升级版,主要用于x86架构。

名称中的 b 代表 "big",表示它支持更大的内核镜像。

特点

支持更大的内核镜像(超过512KB)。

压缩格式,体积较小。

适用于现代x86系统(如UEFI引导)。

适用场景

现代x86架构的Linux系统。

3. uImage

描述

uImage 是U-Boot引导加载程序专用的内核镜像格式。

它在 zImage 或 bzImage 的基础上添加了一个U-Boot头部,包含加载地址、入口地址等信息。

特点

专为U-Boot设计。

包含额外的元数据,便于U-Boot加载和引导。

适用场景

使用U-Boot引导的嵌入式系统(如ARM架构)。

4. Image

描述

Image 是未经压缩的内核镜像格式。

它是内核编译后直接生成的原始二进制文件。

特点

未压缩,体积较大。

加载速度快(无需解压缩)。

适用场景

内存充足且对启动速度要求较高的系统。

5. FIT Image(Flattened Image Tree)

描述

FIT Image 是一种灵活的镜像格式,支持将内核、设备树、RAM磁盘等多个组件打包到一个镜像中。

它基于设备树(Device Tree)的概念,适用于复杂的嵌入式系统。

特点

支持多组件打包。

灵活性高,适合复杂的引导需求。

适用场景

现代嵌入式系统(如ARM架构)。

需要同时加载内核、设备树和初始RAM磁盘的系统。

6. vmlinux

描述

vmlinux 是内核编译后生成的ELF(Executable and Linkable Format)文件。

它是未经压缩和处理的原始内核镜像。

特点

未压缩,体积最大。

包含调试信息,适合调试和分析。

适用场景

内核开发和调试。

7. vmlinuz

描述

vmlinuz 是 vmlinux 的压缩版本,通常用于x86架构的Linux发行版。

它是 zImage 或 bzImage 的另一种形式。

特点

压缩格式,体积较小。

适用于x86架构的Linux系统。

适用场景

桌面和服务器Linux系统。

8. XIP Kernel(Execute In Place)

描述

XIP Kernel 是一种可以直接在存储设备上执行的内核镜像格式。

它不需要将内核加载到内存中,直接从存储设备(如NOR Flash)执行。

特点

节省内存空间。

执行速度较慢(受存储设备速度限制)。

适用场景

内存非常有限的嵌入式系统。

嵌入式Linux中常用的镜像格式

在嵌入式Linux开发中,最常见的镜像格式是 uImage 和 FIT Image,因为它们专为嵌入式系统设计,支持U-Boot引导加载程序,并且可以灵活地处理内核、设备树和初始RAM磁盘。

uImage 示例

# 使用 mkimage 工具生成 uImage
mkimage -A arm -T kernel -C none -a 0x80008000 -e 0x80008000 -n "Linux Kernel" -d zImage uImage

FIT Image 示例

# 使用 mkimage 工具生成 FIT Image
mkimage -f kernel.its kernel.itb

2.内核中申请内存有哪几个函数?有什么区别?

1. kmalloc()

作用:用于分配小块内存(通常小于 4 KB,一般用于 SLAB/SLUB 分配器)。

返回值:返回一个指向物理连续内存的指针。

优点

速度快,适用于小块内存分配。

分配的内存是物理连续的,适用于 DMA 等场景。

缺点

不能保证分配大块内存(超过单个页面时,可能失败)

void *ptr = kmalloc(1024, GFP_KERNEL); // 分配 1024 字节内存
if (!ptr) printk("kmalloc failed!\n");

2. kzalloc()

作用:类似 kmalloc(),但会自动清零分配的内存(等价于 kmalloc() + memset(0))。

void *ptr = kzalloc(1024, GFP_KERNEL);

3. vmalloc()

作用:用于分配大块内存(超过单个页面),但是分配的内存是虚拟地址连续的,物理地址不一定连续。

适用于

需要大块内存但不需要物理连续性的场景,如驱动的缓冲区。

缺点

由于页表映射,访问速度比 kmalloc() 分配的内存慢。

不能用于 DMA(因为物理地址不连续)

void *ptr = vmalloc(1024 * 1024); // 分配 1MB 内存

4. vzalloc()

作用:类似 vmalloc(),但会自动清零分配的内存。

void *ptr = vzalloc(1024 * 1024);
函数物理连续虚拟地址连续适用场景
kmalloc()小块内存,物理连续,可用于 DMA
kzalloc()kmalloc() + 清零
vmalloc()大块内存,物理不连续,不能用于 DMA
vzalloc()vmalloc() + 清零
alloc_pages()以页为单位分配,适用于页级管理
get_free_pages()类似 alloc_pages(),但返回虚拟地址
dma_alloc_coherent()专用于 DMA,返回设备可访问的地址

ioremap() 在内核中的作用

在 Linux 内核驱动开发中,ioremap() 主要用于将物理地址映射到内核的虚拟地址空间,使 CPU 可以访问设备寄存器外部存储器

ioremap() 相关函数

函数作用适用场景
ioremap()将物理地址映射为不可缓存的虚拟地址访问 MMIO(内存映射 I/O),如外设寄存器
ioremap_nocache()ioremap() 的别名,确保不使用 CPU 缓存旧版 API,现已废弃,等同于 ioremap()
ioremap_wc()写合并(Write Combining),提高写入速度适用于帧缓冲等高速写操作
ioremap_cache()允许使用 CPU 缓存适用于 RAM 访问,提高访问效率
iounmap()解除 ioremap() 映射释放内存映射资源

3.什么是内核空间,用户空间?

4.为什么需要区分内核空间与用户空间?

在 CPU 的所有指令中,,有些指令是非常危险的,如果错用,将导致系统崩溃,比如清内存、设置时钟等。如果允许所有的程序都可以使用这些指令,那么系统崩溃的概率将大大增加。
所以,CPU 将指令分为特权指令和非特权指令,对于那些危险的指令,只允许操作系统及其相关模块使用,普通应用程序只能使用那些不会造成灾难的指令。比如 Intel 的 CPU 将特权等级分为4个级别:Ring0~Ring3.
其实 Linux 系统只使用了 Ring0 和 Ring3 两个运行级别(Windows 系统也是一样的)。当进程运行在Ring3 级别时被称为运行在用户态,而运行在 Ring0 级别时被称为运行在内核态。

5.什么是内核态和用户态?

当进程运行在内核空间时就处于内核态,而进程运行在用户空间时则处于用户态。
在内核态下,进程运行在内核地址空间中,此时CPU可以执行任何指令。运行的代码也不受任何的限制,可以自由地访问任何有效地址,也可以直接进行端口的访问。
在用户态下,进程运行在用户地址空间中,被执行的代码要受到 CPU 的诸多检查,它们只能访问映射其地址空间的页表项中规定的在用户态下可访问页面的虚拟地址,且只能对任务状态段(TSS)中 I/0 许可位图(IO Permission Bitmap)中规定的可访问端口进行直接访问。
对于以前的 DOS 操作系统来说,是没有内核空间、用户空间以及内核态、用户态这些概念的。可以认为所有的代码都是运行在内核态的,因而,用户编写的应用程序代码可以很容易的让操作系统崩溃掉。
对于 Linux 来说,通过区分内核空间和用户空间的设计,隔离了操作系统代码(操作系统的代码要比应用程序的代码健壮很多)与应用程序代码。即便是单个应用程序出现错误,也不会影响到操作系统的稳定性,这样其它的程序还可以正常的运行(Linux 可是个多任务系统啊!)。所以,区分内核空间和用户空间本质上是要提高操作系统的稳定性及可用性。

在 Linux 及其他现代操作系统中,内核态(Kernel Mode)用户态(User Mode) 是 CPU 运行的两种模式,主要用于隔离用户进程和操作系统核心代码,确保系统稳定性和安全性。

特性内核态(Kernel Mode)用户态(User Mode)
权限级别高(Ring 0)低(Ring 3)
可访问资源访问所有 CPU 指令和硬件资源只能访问进程自己的虚拟地址空间
内存访问访问整个物理内存只能访问自身进程的虚拟内存
I/O 访问允许直接访问 I/O 设备不能直接访问 I/O 设备
CPU 指令可执行特权指令(如 clisti只能执行非特权指令
切换方式通过 系统调用(syscall) 进入通过 系统调用返回sigreturn 退出

6.用户空间与内核通信方式有哪些?

1. 系统调用(System Call)

原理:

用户空间调用 glibc 提供的 API(如 open()read()),最终进入内核态执行对应的 sys_xxx() 函数。

通过 syscall 指令(x86_64)或 int 0x80(x86)切换到内核态。

适用场景:

文件操作(open()read()write()

进程管理(fork()execve()

设备驱动访问(ioctl()

#include <stdio.h>
#include <unistd.h>int main() {char buffer[128];int n = read(0, buffer, sizeof(buffer));  // 调用系统调用 sys_read()write(1, buffer, n);  // 调用系统调用 sys_write()return 0;
}

2.ioctl(I/O 控制)

原理:

ioctl()(I/O Control)是 系统调用,用于对设备驱动进行特殊操作,如配置 GPIO、电机控制、传感器读取等。

设备驱动程序通过 unlocked_ioctl 处理 ioctl 请求。

适用场景:

设备驱动程序的参数设置(如波特率、模式)

发送命令到内核

#include <stdio.h>
#include <fcntl.h>
#include <sys/ioctl.h>#define LED_ON  _IOW('L', 1, int)
#define LED_OFF _IOW('L', 2, int)int main() {int fd = open("/dev/my_led", O_RDWR);if (fd < 0) {perror("open");return -1;}ioctl(fd, LED_ON);  // 控制 LED 亮ioctl(fd, LED_OFF); // 控制 LED 灭close(fd);return 0;
}

3. procfs(/proc 文件系统)

原理:

/proc 是一个虚拟文件系统,用于访问内核状态信息

通过 cat /proc/my_proc,可以获取内核数据。

适用场景:

进程信息(/proc/<PID>

内核参数(/proc/sys/

设备信息(/proc/devices

static struct proc_dir_entry *proc_entry;ssize_t my_proc_read(struct file *file, char __user *buf, size_t count, loff_t *pos) {char message[] = "Hello from Kernel!\n";return simple_read_from_buffer(buf, count, pos, message, sizeof(message));
}static int __init my_init(void) {proc_entry = proc_create("my_proc", 0444, NULL, &(struct proc_ops){ .proc_read = my_proc_read });return 0;
}
static void __exit my_exit(void) { remove_proc_entry("my_proc", NULL); }

用户程序访问:

cat /proc/my_proc

4. sysfs(/sys 文件系统)

原理:

/sys 是一个 /proc 更结构化 的文件系统,主要用于设备和驱动信息的交互。

可以用 echocat 直接修改或获取设备信息

适用场景:

设备驱动的参数调节(如 LED 亮度、风扇转速)

设备状态监测

static struct kobject *kobj;
static int my_value = 0;static ssize_t show_value(struct kobject *kobj, struct kobj_attribute *attr, char *buf) {return sprintf(buf, "%d\n", my_value);
}
static ssize_t store_value(struct kobject *kobj, struct kobj_attribute *attr, const char *buf, size_t count) {sscanf(buf, "%d", &my_value);return count;
}static struct kobj_attribute my_attr = __ATTR(my_value, 0660, show_value, store_value);static int __init my_init(void) {kobj = kobject_create_and_add("my_kobj", kernel_kobj);sysfs_create_file(kobj, &my_attr.attr);return 0;
}

用户访问:

echo 10 > /sys/kernel/my_kobj/my_value  # 写入
cat /sys/kernel/my_kobj/my_value        # 读取
方式适用场景适合数据量复杂度
System Call通用
ioctl设备控制⭐⭐
procfs状态查询
sysfs设备参数
Netlink事件通知中等⭐⭐⭐
mmap大数据⭐⭐⭐

7.内核链表为什么具有通用性?

内核中由于要管理大量的设备,但是各种设备各不相同,必须将他们统一起来管理,于是内核设计者就想到了使用通用链表来处理,通用链表看似神秘,实际上就是双向循环链表,这个链表的每个节点都是只有指针域,没有任何数据域。

使用通用链表的好处是
1.通用链表中每个节点中没有数据域,也就是说无论数据结构有多复杂在链表中只有前后级指针。2.如果一个数据结构(即是描述设备的设备结构体)想要用通用链表管理,只需要在结构体中包含节
点的字段即可。
3.双向链表可以从任意一个节点的前后遍历整个链表,遍历非常方便。
4.使用循环链表使得可以不断地循环遍历管理节点,像进程的调度:操作系统会把就绪的进程放在一个管理进程的就绪队列的通用链表中管理起来,循环不断地,为他们分配时间片,获得cpu进行周而复始的进程调度。

注意:在RTOS操作系统中,每个task的执行顺序,不同状态,队列,信号量,互斥锁等等,底层都是使用链表的。

特性传统链表Linux 内核链表
是否绑定数据类型(只能存 int 或特定结构体)(适用于任何结构体)
是否循环
是否双向可能是单链表
是否支持统一 API(不同数据类型需要不同的操作)(统一 API)
是否易扩展扩展困难易扩展

8.应用程序中open()在linux中执行过程中是如何从用户空间到内核空间?

open() 是 Linux 系统调用(System Call)之一,用于打开文件或设备。它涉及从用户空间(User Space)切换到内核空间(Kernel Space)的过程,具体涉及系统调用、中断、文件系统、VFS(虚拟文件系统)等机制

如下是流程:

open() 先通过 glibc 触发系统调用

进入内核后,先由 VFS 解析路径

如果是普通文件,调用 ext4 等文件系统的 open

如果是设备文件,调用设备驱动 file_operations->open()

最终返回文件描述符 fd,用户进程可以使用 read()write() 操作

open()glibc(C 标准库) 中的实现:

int open(const char *pathname, int flags, mode_t mode) {return syscall(SYS_openat, AT_FDCWD, pathname, flags, mode);
}

syscall(SYS_openat, ...) 通过 syscall 指令 进入 内核空间

这个过程发生在 arch/x86/entry/entry_64.S,主要步骤:

syscall 指令:CPU 从用户模式(Ring 3)切换到内核模式(Ring 0)

sys_openat() 被调用(定义在 fs/open.c)。

fs/open.c 中:

long do_sys_open(int dfd, const char __user *filename, int flags, umode_t mode) {struct open_how how = build_open_how(flags, mode);return do_filp_open(dfd, filename, &how);
}

fs/namei.c

struct file *do_filp_open(int dfd, const char __user *filename, struct open_how *how) {struct nameidata nd;struct file *filp;filp = path_openat(&nd, how, LOOKUP_FOLLOW);return filp;
}

假设 open() 操作的是 ext4 文件:

  • VFS 通过 inode_operations->lookup() 找到 ext4_lookup()
  • 调用 file_operations->open()(如 ext4_file_open())。

ext4_file_open()(位于 fs/ext4/file.c):

int ext4_file_open(struct inode *inode, struct file *file) {// 执行特定文件系统的打开操作return generic_file_open(inode, file);
}
步骤主要操作
1. 用户空间调用glibc 调用 syscall(SYS_openat)
2. 进入内核空间syscall 指令触发 sys_openat()
3. VFS 处理do_filp_open() 解析路径,查找文件
4. 文件系统层ext4_file_open()device->fops->open()
5. 生成文件描述符fd 存入 task_struct->files 并返回

9.怎么申请大块内核内存?

vmalloc

相关文章:

嵌入式知识点总结 Linux驱动 (五)-linux内核

针对于嵌入式软件杂乱的知识点总结起来&#xff0c;提供给读者学习复习对下述内容的强化。 目录 1.内核镜像格式有几种&#xff1f;分别有什么区别&#xff1f; 2.内核中申请内存有哪几个函数&#xff1f;有什么区别&#xff1f; 3.什么是内核空间&#xff0c;用户空间&…...

zabbix7 配置字体 解决中文乱码问题(随手记)

目录 问题网传的方法&#xff08;无效&#xff09;正确的修改方式步骤 问题 zabbix 最新数据 中&#xff0c;图标的中文显示不出。 网传的方法&#xff08;无效&#xff09; 网传有一个方法&#xff1a;上传字体文件到/usr/share/zabbix/assets/fonts&#xff1b;修改/usr/…...

预测不规则离散运动的下一个结构

有一个点在19*19的平面上运动&#xff0c;运动轨迹为 一共移动了90步&#xff0c;顺序为 y x y x y x 0 17 16 30 10 8 60 15 15 1 3 6 31 10 7 61 14 15 2 12 17 32 9 9 62 16 15 3 4 12 33 10 9 63 18 15 4 3 18 34 15 12 6…...

CTFSHOW-WEB入门-命令执行29-32

题目&#xff1a;web 29 题目&#xff1a;解题思路&#xff1a;分析代码&#xff1a; error_reporting(0); if(isset($_GET[c])){//get一个c的参数$c $_GET[c];//赋值给Cif(!preg_match("/flag/i", $c)){eval($c);//if C变量里面没有flag&#xff0c;那么就执行C…...

SQL Server 建立每日自动log备份的维护计划

SQLServer数据库可以使用维护计划完成数据库的自动备份&#xff0c;下面以在SQL Server 2012为例说明具体配置方法。 1.启动SQL Server Management Studio&#xff0c;在【对象资源管理器】窗格中选择数据库实例&#xff0c;然后依次选择【管理】→【维护计划】选项&#xff0…...

doris:HLL

HLL是用作模糊去重&#xff0c;在数据量大的情况性能优于 Count Distinct。HLL的导入需要结合hll_hash等函数来使用。更多文档参考HLL。 使用示例​ 第 1 步&#xff1a;准备数据​ 创建如下的 csv 文件&#xff1a;test_hll.csv 1001|koga 1002|nijg 1003|lojn 1004|lofn …...

双层Git管理项目,github托管显示正常

双层Git管理项目&#xff0c;github托管显示正常 背景 在写React项目时&#xff0c;使用Next.js,该项目默认由git托管。但是我有在项目代码外层记笔记的习惯&#xff0c;我就在外层使用了git托管。 目录如下 code 层内也有.git 文件&#xff0c;对其托管。 我没太在意&…...

准备知识——旋转机械的频率和振动基础

旋转频率&#xff0c;也称为转速或旋转速率&#xff08;符号ν&#xff0c;小写希腊字母nu&#xff0c;也作n&#xff09;&#xff0c;是物体绕轴旋转的频率。其国际单位制单位是秒的倒数(s −1 )&#xff1b;其他常见测量单位包括赫兹(Hz)、每秒周期数(cps) 和每分钟转数(rpm)…...

知识库管理驱动企业知识流动与工作协同创新模式

内容概要 知识库管理在现代企业中扮演着至关重要的角色&#xff0c;其价值不仅体现在知识的积累&#xff0c;还在于通过优质的信息流动促进协作与创新。有效的知识库能够将分散的信息整合为有序、易于访问的资源&#xff0c;为员工提供实时支持&#xff0c;进而提升整体工作效…...

CMake常用命令指南(CMakeList.txt)

CMakeList从入门到精通的文章有很多不再赘述&#xff08; 此处附带一篇优秀的博文链接&#xff1a;一个简单例子&#xff0c;完全入门CMake语法与CMakeList编写 &#xff09;。 本文主要列举 CMake 中常用命令的详细说明、优缺点分析以及推荐做法&#xff0c;以更好地理解和灵…...

【回溯+剪枝】找出所有子集的异或总和再求和 全排列Ⅱ

文章目录 1863. 找出所有子集的异或总和再求和解题思路&#xff1a;子集问题解法&#xff08;回溯 剪枝&#xff09;47. 全排列 II解题思路&#xff1a;排序 回溯 剪枝 1863. 找出所有子集的异或总和再求和 1863. 找出所有子集的异或总和再求和 一个数组的 异或总和 定义为…...

中国技术突破对国际格局的多维影响与回应

链接地址&#xff1a; https://download.csdn.net/download/wanggang130532/90323798https://download.csdn.net/download/wanggang130532/90323798...

【漫话机器学习系列】068.网格搜索(GridSearch)

网格搜索&#xff08;Grid Search&#xff09; 网格搜索&#xff08;Grid Search&#xff09;是一种用于优化机器学习模型超参数的技术。它通过系统地遍历给定的参数组合&#xff0c;找出使模型性能达到最优的参数配置。 网格搜索的核心思想 定义参数网格 创建一个包含超参数值…...

元宇宙下的Facebook:虚拟现实与社交的结合

随着科技的不断进步&#xff0c;虚拟现实&#xff08;VR&#xff09;技术逐渐从科幻走入现实&#xff0c;成为人们探索未来社交方式的重要工具。在这一浪潮中&#xff0c;Facebook&#xff08;现为Meta&#xff09;作为全球领先的社交平台&#xff0c;正在积极布局虚拟现实和元…...

记忆力训练day08

写作头脑风暴训练 1 集体的头脑风暴&#xff1a; 2 一个人的头脑风暴 没事&#xff0c;你说老师我还没有摸到门道&#xff0c;你去做&#xff0c;做的时候你就会知道什么叫做头脑风暴。记住&#xff0c;不要用脑子就在感觉里面&#xff0c;你究竟想给人呈现一种什么样的文章&am…...

崇州市街子古镇正月初一繁华剪影

今天是蛇年正月初一&#xff0c;下午笔者步出家门&#xff0c;逛到了崇州市街子古镇井水街&#xff0c;想看看景象如何。结果看到的是车水马龙、人流如织&#xff0c;繁花似锦&#xff0c;热闹非凡&#xff0c;原来今天开始预订此地摆下的长街宴。心里高兴&#xff0c;便用手机…...

websocket webworker教程及应用

WebSocket 和 Web Workers 是两种不同的 Web 技术&#xff0c;分别用于实现实时通信和后台线程处理。以下是它们的简要教程&#xff1a; WebSocket 教程 1. 什么是 WebSocket&#xff1f; WebSocket 是一种在单个 TCP 连接上进行全双工通信的协议。它允许服务器主动向客户端推…...

【后端】Flask

长期更新&#xff0c;建议关注收藏点赞&#xff01; 实例1 Jinja2 是 Flask 和 Django 使用的 模板引擎&#xff0c;它允许你在 HTML 中嵌入 Python 代码&#xff0c;以动态生成页面内容。Jinja2 语法类似于 Django 模板&#xff0c;并支持变量、条件判断、循环、过滤器等。 fr…...

【cran Archive R包的安装方式】

cran Archive R包的安装方式 添加链接描述 1.包被cran移除 2.包要求的R语言版本与你电脑上的版本不相符 ad archive包的网址或者是下载到工作目录下&#xff0c;ad等于文件名 install,packages(ad repos NULL)...

如何用matlab画一条蛇

文章目录 源代码运行结果代码说明结果 源代码 % 画蛇的代码 % 2025-01-28/Ver1 % 清空环境 clc; clear; close all;% 定义蛇的身体坐标 t linspace(0, 4*pi, 100); % 参数化变量 x t; % x坐标 y sin(t) 0.5 * sin(3*t); % y坐标&#xff0c;形成更复…...

逻辑回归:给不确定性划界的分类大师

想象你是一名医生。面对患者的检查报告&#xff08;肿瘤大小、血液指标&#xff09;&#xff0c;你需要做出一个**决定性判断**&#xff1a;恶性还是良性&#xff1f;这种“非黑即白”的抉择&#xff0c;正是**逻辑回归&#xff08;Logistic Regression&#xff09;** 的战场&a…...

工程地质软件市场:发展现状、趋势与策略建议

一、引言 在工程建设领域&#xff0c;准确把握地质条件是确保项目顺利推进和安全运营的关键。工程地质软件作为处理、分析、模拟和展示工程地质数据的重要工具&#xff0c;正发挥着日益重要的作用。它凭借强大的数据处理能力、三维建模功能、空间分析工具和可视化展示手段&…...

Python爬虫(二):爬虫完整流程

爬虫完整流程详解&#xff08;7大核心步骤实战技巧&#xff09; 一、爬虫完整工作流程 以下是爬虫开发的完整流程&#xff0c;我将结合具体技术点和实战经验展开说明&#xff1a; 1. 目标分析与前期准备 网站技术分析&#xff1a; 使用浏览器开发者工具&#xff08;F12&…...

今日科技热点速览

&#x1f525; 今日科技热点速览 &#x1f3ae; 任天堂Switch 2 正式发售 任天堂新一代游戏主机 Switch 2 今日正式上线发售&#xff0c;主打更强图形性能与沉浸式体验&#xff0c;支持多模态交互&#xff0c;受到全球玩家热捧 。 &#x1f916; 人工智能持续突破 DeepSeek-R1&…...

Linux nano命令的基本使用

参考资料 GNU nanoを使いこなすnano基础 目录 一. 简介二. 文件打开2.1 普通方式打开文件2.2 只读方式打开文件 三. 文件查看3.1 打开文件时&#xff0c;显示行号3.2 翻页查看 四. 文件编辑4.1 Ctrl K 复制 和 Ctrl U 粘贴4.2 Alt/Esc U 撤回 五. 文件保存与退出5.1 Ctrl …...

为什么要创建 Vue 实例

核心原因:Vue 需要一个「控制中心」来驱动整个应用 你可以把 Vue 实例想象成你应用的**「大脑」或「引擎」。它负责协调模板、数据、逻辑和行为,将它们变成一个活的、可交互的应用**。没有这个实例,你的代码只是一堆静态的 HTML、JavaScript 变量和函数,无法「活」起来。 …...

Spring AI Chat Memory 实战指南:Local 与 JDBC 存储集成

一个面向 Java 开发者的 Sring-Ai 示例工程项目&#xff0c;该项目是一个 Spring AI 快速入门的样例工程项目&#xff0c;旨在通过一些小的案例展示 Spring AI 框架的核心功能和使用方法。 项目采用模块化设计&#xff0c;每个模块都专注于特定的功能领域&#xff0c;便于学习和…...

LOOI机器人的技术实现解析:从手势识别到边缘检测

LOOI机器人作为一款创新的AI硬件产品&#xff0c;通过将智能手机转变为具有情感交互能力的桌面机器人&#xff0c;展示了前沿AI技术与传统硬件设计的完美结合。作为AI与玩具领域的专家&#xff0c;我将全面解析LOOI的技术实现架构&#xff0c;特别是其手势识别、物体识别和环境…...

论文阅读:Matting by Generation

今天介绍一篇关于 matting 抠图的文章&#xff0c;抠图也算是计算机视觉里面非常经典的一个任务了。从早期的经典算法到如今的深度学习算法&#xff0c;已经有很多的工作和这个任务相关。这两年 diffusion 模型很火&#xff0c;大家又开始用 diffusion 模型做各种 CV 任务了&am…...

智能职业发展系统:AI驱动的职业规划平台技术解析

智能职业发展系统&#xff1a;AI驱动的职业规划平台技术解析 引言&#xff1a;数字时代的职业革命 在当今瞬息万变的就业市场中&#xff0c;传统的职业规划方法已无法满足个人和企业的需求。据统计&#xff0c;全球每年有超过2亿人面临职业转型困境&#xff0c;而企业也因此遭…...