透过 /proc 看见内核:Linux 虚拟文件系统与 systemd 初始化初探

当我们在终端中输入 pstopcat /proc/cpuinfo 等命令时,是否思考过这些信息来自哪里?为什么无需启动任何守护进程,就能实时读取系统负载、内存占用,甚至内核版本?这一切的答案,都藏在 Linux 系统中的一个目录——/proc/proc 是 Linux 提供的一个虚拟文件系统(procfs),它不占用实际磁盘空间,而是由内核在内存中动态生成的。这个特殊的文件系统为用户空间提供了观察和控制内核状态的窗口,贯穿系统生命周期的方方面面。

尤其值得注意的是 /proc/1/,它代表系统中第一个用户空间进程 systemd。理解这个目录背后的机制,不仅能揭示 Linux 系统的初始化流程,还能帮助我们理解容器隔离、性能调优、安全监控等关键场景。本文将从 /proc 的结构与用途出发,结合 systemd 的初始化机制,逐步解析虚拟文件系统的内核实现原理,以及它在现代 Linux 中的意义。

一.深入 /proc:内核与进程信息的大本营

/proc 虚拟文件系统的根目录下,既包含大量以数字命名的子目录,也包含一些代表系统运行状态的特殊文件。这些内容可以分为两大类:

在这里插入图片描述

1.进程相关目录(/proc/[pid]/

系统中每一个正在运行的进程,都会在 /proc 下有一个以其进程号(PID)命名的目录,比如 /proc/1//proc/1123/ 等。这个目录中的文件反映了该进程的实时状态,例如:

文件/目录说明
cmdline启动命令及其参数
cwd当前工作目录(符号链接)
exe可执行程序路径(符号链接)
status人类可读的进程状态信息
stat更详细的进程状态,ps 命令依赖此文件
fd/文件描述符目录,列出该进程打开的所有文件
maps内存映射信息(代码段、数据段、共享库等)
stack内核栈的回溯信息(用于调试)

通过这些文件,我们可以轻松监控、调试和分析系统中任意一个进程。例如:

cat /proc/$$/cmdline     # 查看当前 shell 的启动命令
ls -l /proc/1/fd         # 查看 PID 1 打开的文件描述符
cat /proc/1/status       # 查看 systemd 的进程状态信息

2.系统级别信息文件

除了进程目录,/proc 根目录还包含许多关键系统信息,例如:

文件/目录内容
cpuinfoCPU 型号、核数、频率等
meminfo内存使用情况
uptime系统启动至今的时长
loadavg系统负载情况
modules已加载的内核模块
version内核版本号
stat系统级统计信息(进程数、CPU 使用等)
mounts / mountinfo当前挂载的文件系统
filesystems支持的文件系统类型

3.动态内核参数接口:/proc/sys/

这一目录下的内容对应内核的可调参数,通过它我们可以动态修改内核行为,如网络设置、内存策略、进程限制等:

cat /proc/sys/net/ipv4/ip_forward        # 查看 IP 转发是否开启
echo 1 > /proc/sys/net/ipv4/ip_forward   # 启用 IP 转发

二、/proc/1:揭开第一个用户进程 systemd 的面纱

在 Linux 系统启动完成后,用户空间的第一个进程总是拥有一个固定的 PID —— 1。它通常是我们熟悉的 systemd,也是整个用户空间中最重要的“总管”。

1.systemd 是怎么启动的?

整个系统的启动过程大致如下:

[BIOS/UEFI][GRUB 等引导加载器][Linux 内核加载][init进程启动]

当内核完成自身初始化后,它会尝试执行第一个用户空间进程,通常的查找顺序为:

  1. 内核启动参数中的 init= 指定的路径(如 init=/bin/sh
  2. /sbin/init
  3. /etc/init
  4. /bin/init
  5. /bin/sh

而在现代 Linux 系统中,这个 “init” 通常是 /lib/systemd/systemd 的软链接,或者直接是 /sbin/init 指向 systemd

可以通过如下命令验证:

ls -l /sbin/init
lrwxrwxrwx 1 root root 20 1122  2023 /sbin/init -> /lib/systemd/systemd

所以,当看到 /proc/1/ 时,这个目录下的信息正对应着 systemd 的运行状态。

2.观察 /proc/1/ —— 进程 systemd 的现场

我们可以进入 /proc/1/,查看这个特殊进程的启动方式:

 tr '\0' ' ' < /proc/1/cmdline
/sbin/init auto noprompt splash

这是进程 1(systemd)的命令行启动参数:

  • /sbin/init:可执行程序路径
  • autonopromptsplash:传递给 init 的启动参数

这说明内核启动后,通过如下方式执行了第一个进程:

execve("/sbin/init", ["/sbin/init", "auto", "noprompt", "splash"], envp);

那内核是“怎么”启动这个 /sbin/init 的?

当 Linux 内核完成自身初始化后,它会在 init/main.c 中尝试执行第一个用户空间进程(以下内核源码来自6.12 init/main.c):

if (execute_command) {ret = run_init_process(execute_command);if (!ret)return 0;panic("Requested init %s failed (error %d).", execute_command, ret);
}

如果内核启动参数中传入了 init=xxx,那么它优先尝试执行这个指定的路径,否则继续尝试默认路径:

if (CONFIG_DEFAULT_INIT[0] != '\0') {ret = run_init_process(CONFIG_DEFAULT_INIT);...
}

这是编译内核时指定的默认 init 路径,通常不会设置。然后进入备选方案:

if (!try_to_run_init_process("/sbin/init") ||!try_to_run_init_process("/etc/init") ||!try_to_run_init_process("/bin/init") ||!try_to_run_init_process("/bin/sh"))return 0;

内核尝试从多个默认路径中依次查找有效的 init 进程,这就是我们看到 /sbin/init 的来源。

3./lib/systemd/systemd 到底是什么

这个目录里是 systemd 的主程序 —— 一个ELF 可执行文件,由 systemd 项目编译生成,功能非常强大,是整个用户空间初始化和服务管理的核心。

可以直接用 file 命令查看它的本质:

file /lib/systemd/systemd
/lib/systemd/systemd: ELF 64-bit LSB pie executable, x86-64, version 1 (SYSV), dynamically linked, interpreter /lib64/ld-linux-x86-64.so.2, BuildID[sha1]=2ab06decf08c9378367b98f3e592473ea32a5b3c, for GNU/Linux 3.2.0, stripped

这表明它是一个编译好的 64 位 ELF 可执行文件,能被内核通过 execve() 调用执行。

我们可以使用objdump去反编译 systemd:

objdump -x /lib/systemd/systemd/lib/systemd/systemd:     文件格式 elf64-x86-64
/lib/systemd/systemd
体系结构:i386:x86-64, 标志 0x00000150:
HAS_SYMS, DYNAMIC, D_PAGED
起始地址 0x0000000000042690程序头:PHDR off    0x0000000000000040 vaddr 0x0000000000000040 paddr 0x0000000000000040 align 2**3filesz 0x00000000000002d8 memsz 0x00000000000002d8 flags r--INTERP off    0x0000000000000318 vaddr 0x0000000000000318 paddr 0x0000000000000318 align 2**0filesz 0x000000000000001c memsz 0x000000000000001c flags r--LOAD off    0x0000000000000000 vaddr 0x0000000000000000 paddr 0x0000000000000000 align 2**12filesz 0x0000000000035af8 memsz 0x0000000000035af8 flags r--LOAD off    0x0000000000036000 vaddr 0x0000000000036000 paddr 0x0000000000036000 align 2**12filesz 0x00000000000df58d memsz 0x00000000000df58d flags r-xLOAD off    0x0000000000116000 vaddr 0x0000000000116000 paddr 0x0000000000116000 align 2**12filesz 0x000000000005ea10 memsz 0x000000000005ea10 flags r--LOAD off    0x0000000000174e90 vaddr 0x0000000000175e90 paddr 0x0000000000175e90 align 2**12filesz 0x000000000004e28c memsz 0x00000000000505b0 flags rw-DYNAMIC off    0x00000000001c0780 vaddr 0x00000000001c1780 paddr 0x00000000001c1780 align 2**3filesz 0x0000000000000280 memsz 0x0000000000000280 flags rw-NOTE off    0x0000000000000338 vaddr 0x0000000000000338 paddr 0x0000000000000338 align 2**3filesz 0x0000000000000030 memsz 0x0000000000000030 flags r--NOTE off    0x0000000000000368 vaddr 0x0000000000000368 paddr 0x0000000000000368 align 2**2filesz 0x0000000000000044 memsz 0x0000000000000044 flags r--
0x6474e553 off    0x0000000000000338 vaddr 0x0000000000000338 paddr 0x0000000000000338 align 2**3filesz 0x0000000000000030 memsz 0x0000000000000030 flags r--
EH_FRAME off    0x00000000001572f0 vaddr 0x00000000001572f0 paddr 0x00000000001572f0 align 2**2filesz 0x0000000000002dc4 memsz 0x0000000000002dc4 flags r--STACK off    0x0000000000000000 vaddr 0x0000000000000000 paddr 0x0000000000000000 align 2**4filesz 0x0000000000000000 memsz 0x0000000000000000 flags rw-RELRO off    0x0000000000174e90 vaddr 0x0000000000175e90 paddr 0x0000000000175e90 align 2**0filesz 0x000000000004e170 memsz 0x000000000004e170 flags r--动态节:NEEDED               libsystemd-shared-249.soNEEDED               libseccomp.so.2NEEDED               libselinux.so.1NEEDED               libmount.so.1NEEDED               libpam.so.0NEEDED               libaudit.so.1NEEDED               libkmod.so.2NEEDED               libapparmor.so.1NEEDED               libc.so.6RUNPATH              /lib/systemdINIT                 0x0000000000036000FINI                 0x0000000000115580INIT_ARRAY           0x0000000000175e90INIT_ARRAYSZ         0x0000000000000008FINI_ARRAY           0x0000000000175e98FINI_ARRAYSZ         0x0000000000000008GNU_HASH             0x00000000000003b0STRTAB               0x0000000000007ac0SYMTAB               0x00000000000004a0STRSZ                0x0000000000005c20SYMENT               0x0000000000000018DEBUG                0x0000000000000000PLTGOT               0x00000000001c1a00PLTRELSZ             0x0000000000006d08PLTREL               0x0000000000000007JMPREL               0x000000000002edf0RELA                 0x000000000000e2b8RELASZ               0x0000000000020b38RELAENT              0x0000000000000018FLAGS                0x0000000000000008FLAGS_1              0x0000000008000001VERNEED              0x000000000000e0b8VERNEEDNUM           0x0000000000000007VERSYM               0x000000000000d6e0RELACOUNT            0x0000000000001346版本引用:required from libapparmor.so.1:0x06236661 0x00 24 APPARMOR_1.10x02363623 0x00 20 APPARMOR_2.130x02363620 0x00 16 APPARMOR_2.10required from libmount.so.1:0x03a775e9 0x00 17 MOUNT_2.190x03a775f0 0x00 12 MOUNT_2.200x03a775f6 0x00 10 MOUNT_2.26required from libpam.so.0:0x04682f60 0x00 09 LIBPAM_1.0required from libselinux.so.1:0x0edb87f0 0x00 06 LIBSELINUX_1.0required from libkmod.so.2:0x07026af5 0x00 05 LIBKMOD_5required from libsystemd-shared-249.so:0x047c3134 0x00 04 SD_SHAREDrequired from libc.so.6:0x06969188 0x00 26 GLIBC_2.280x06969186 0x00 25 GLIBC_2.260x0d696918 0x00 23 GLIBC_2.80x09691973 0x00 22 GLIBC_2.3.30x06969197 0x00 21 GLIBC_2.170x06969194 0x00 19 GLIBC_2.140x0d696919 0x00 18 GLIBC_2.90x069691b4 0x00 15 GLIBC_2.340x06969190 0x00 14 GLIBC_2.100x0d696914 0x00 13 GLIBC_2.40x06969185 0x00 11 GLIBC_2.250x069691b3 0x00 08 GLIBC_2.330x0d696917 0x00 07 GLIBC_2.70x09691a75 0x00 03 GLIBC_2.2.50x09691974 0x00 02 GLIBC_2.3.4节:
Idx Name          Size      VMA               LMA               File off  Algn0 .interp       0000001c  0000000000000318  0000000000000318  00000318  2**0CONTENTS, ALLOC, LOAD, READONLY, DATA1 .note.gnu.property 00000030  0000000000000338  0000000000000338  00000338  2**3CONTENTS, ALLOC, LOAD, READONLY, DATA2 .note.gnu.build-id 00000024  0000000000000368  0000000000000368  00000368  2**2CONTENTS, ALLOC, LOAD, READONLY, DATA3 .note.ABI-tag 00000020  000000000000038c  000000000000038c  0000038c  2**2CONTENTS, ALLOC, LOAD, READONLY, DATA4 .gnu.hash     000000ec  00000000000003b0  00000000000003b0  000003b0  2**3CONTENTS, ALLOC, LOAD, READONLY, DATA5 .dynsym       00007620  00000000000004a0  00000000000004a0  000004a0  2**3CONTENTS, ALLOC, LOAD, READONLY, DATA6 .dynstr       00005c20  0000000000007ac0  0000000000007ac0  00007ac0  2**0CONTENTS, ALLOC, LOAD, READONLY, DATA7 .gnu.version  000009d8  000000000000d6e0  000000000000d6e0  0000d6e0  2**1CONTENTS, ALLOC, LOAD, READONLY, DATA8 .gnu.version_r 00000200  000000000000e0b8  000000000000e0b8  0000e0b8  2**3CONTENTS, ALLOC, LOAD, READONLY, DATA9 .rela.dyn     00020b38  000000000000e2b8  000000000000e2b8  0000e2b8  2**3CONTENTS, ALLOC, LOAD, READONLY, DATA10 .rela.plt     00006d08  000000000002edf0  000000000002edf0  0002edf0  2**3CONTENTS, ALLOC, LOAD, READONLY, DATA11 .init         0000001b  0000000000036000  0000000000036000  00036000  2**2CONTENTS, ALLOC, LOAD, READONLY, CODE12 .plt          000048c0  0000000000036020  0000000000036020  00036020  2**4CONTENTS, ALLOC, LOAD, READONLY, CODE13 .plt.got      00000050  000000000003a8e0  000000000003a8e0  0003a8e0  2**4CONTENTS, ALLOC, LOAD, READONLY, CODE14 .plt.sec      000048b0  000000000003a930  000000000003a930  0003a930  2**4CONTENTS, ALLOC, LOAD, READONLY, CODE15 .text         000d639f  000000000003f1e0  000000000003f1e0  0003f1e0  2**4CONTENTS, ALLOC, LOAD, READONLY, CODE16 .fini         0000000d  0000000000115580  0000000000115580  00115580  2**2CONTENTS, ALLOC, LOAD, READONLY, CODE17 .rodata       000412f0  0000000000116000  0000000000116000  00116000  2**5CONTENTS, ALLOC, LOAD, READONLY, DATA18 .eh_frame_hdr 00002dc4  00000000001572f0  00000000001572f0  001572f0  2**2CONTENTS, ALLOC, LOAD, READONLY, DATA19 .eh_frame     0001a958  000000000015a0b8  000000000015a0b8  0015a0b8  2**3CONTENTS, ALLOC, LOAD, READONLY, DATA20 .init_array   00000008  0000000000175e90  0000000000175e90  00174e90  2**3CONTENTS, ALLOC, LOAD, DATA21 .fini_array   00000008  0000000000175e98  0000000000175e98  00174e98  2**3CONTENTS, ALLOC, LOAD, DATA22 .data.rel.ro  0004b8e0  0000000000175ea0  0000000000175ea0  00174ea0  2**5CONTENTS, ALLOC, LOAD, DATA23 .dynamic      00000280  00000000001c1780  00000000001c1780  001c0780  2**3CONTENTS, ALLOC, LOAD, DATA24 .got          000025f8  00000000001c1a00  00000000001c1a00  001c0a00  2**3CONTENTS, ALLOC, LOAD, DATA25 .data         0000011c  00000000001c4000  00000000001c4000  001c3000  2**5CONTENTS, ALLOC, LOAD, DATA26 .bss          00002320  00000000001c4120  00000000001c4120  001c311c  2**5ALLOC27 .gnu_debugaltlink 00000047  0000000000000000  0000000000000000  001c311c  2**0CONTENTS, READONLY28 .gnu_debuglink 00000034  0000000000000000  0000000000000000  001c3164  2**2CONTENTS, READONLY
SYMBOL TABLE:
无符号

我们用 objdump 工具分析 /lib/systemd/systemd 这个 systemd 主程序后可以看到,它是一个结构完整的 ELF 动态链接可执行文件:

  • 它的入口地址由内核调用,是整个用户空间的启动点
  • 它依赖大量核心系统库,如 libselinux、libpam、libmount、libaudit 等
  • 它通过动态链接器 /lib64/ld-linux-x86-64.so.2 加载运行所需库
  • 它的各个段区(.text、.data、.init_array、.got、.plt 等)清晰地定义了 systemd 的功能划分

这说明 systemd 不是一个单纯的“init 工具”,而是连接 Linux 内核与用户空间生态的核心组件。它的结构复杂而严谨,是现代操作系统服务调度的基础。

三、/proc 的内核实现原理

在前面我们看到,/proc 并不是一个普通的文件系统,它里面的文件不会真正存储在磁盘上,而是内核在内存中实时生成的。这种文件系统被称为 虚拟文件系统(Virtual File System),而 /proc 正是 Linux 中最早的虚拟文件系统之一。

那这些文件是如何实现的?我们又是如何通过 cat /proc/cpuinfo 获取到 CPU 信息的呢?

1. procfs 是如何挂载到 /proc 的?

在 Linux 启动的早期阶段,内核会主动调用 proc_root_init() 来初始化 proc 文件系统,并将其挂载到 /proc 目录下:

proc_root_init();           // 初始化 procfs 根目录
mount("proc", "/proc", "proc", 0, NULL);  // 挂载 proc 文件系统

2. 文件内容是怎么来的?——动态生成!

与普通文件不同,/proc 下的文件在访问时才会动态生成内容,不占用任何磁盘空间。以 /proc/cpuinfo 为例:

  • 当你执行 cat /proc/cpuinfo
  • 内核会调用绑定到这个路径上的 show_cpuinfo() 函数
  • 函数读取内核中的 CPU 数据结构(如 cpu_data[]
  • 然后格式化内容返回给用户空间

这依赖于 proc_create()proc_create_single() 这些内核 API:

proc_create("cpuinfo", 0444, NULL, &cpuinfo_proc_ops);

&cpuinfo_proc_ops 是一组 file_operations 函数指针(如 .read.open 等),当你执行 cat 时,就会调用 read() 指针对应的函数来生成输出内容。

3. /proc/[pid]/ 的文件又是怎么实现的?

这部分更有趣 —— 每当有新进程创建时,内核会在 /proc 下创建一个以 PID 为名的目录,并挂载一组与该进程有关的动态文件。这些内容来自于内核中的 task_struct 结构体,它是内核维护的每个进程的核心信息块。

  • /proc/[pid]/status 对应的是当前进程的 task_struct 中各种状态字段
  • /proc/[pid]/fd/ 是根据该进程的文件描述符数组生成的
  • /proc/[pid]/maps 是进程地址空间的内存映射

也就是说,你在 /proc/1234/status 中看到的内容,其实是内核将 task_struct 中的信息格式化后,通过 seq_fileproc_ops 机制动态生成的。

4. /proc/sys/ 与内核参数(sysctl)的关系

/proc/sys/ 是另一个特殊子系统,它与 sysctl 机制联动,允许我们动态修改内核参数

例如:

echo 1 > /proc/sys/net/ipv4/ip_forward

等价于:

sysctl -w net.ipv4.ip_forward=1

这些路径在内核中通过 register_sysctl() 机制注册,并绑定到对应的内核变量上。例如 ip_forward 就是一个内核布尔变量,写入它实际上会影响内核行为。

四、/proc 与容器隔离

在现代 Linux 容器技术(如 Docker、Kubernetes)中,Namespace 是实现隔离的基础,而 /proc 是最直观体现这种隔离的接口之一。

容器通常使用 PID namespace 进行进程号隔离。每个容器中都会挂载一个独立的 /proc,看起来它的 PID 是从 1 开始的,但这只是当前命名空间的视角。

# 宿主机中
ps -ef | grep my-container-process
# PID = 12345# 容器内
ps -ef
# PID = 1(看不到宿主机其他进程)

这时容器内的 /proc 实际上是一个挂载在 proc namespace 视角下的虚拟视图。

/proc/[pid]/ 中的信息是基于当前命名空间 task_struct 中的映射生成的。/proc/self/ 永远指向当前进程/proc/[pid]/,即使是容器内。这让容器内的用户空间感知不到外部系统,增强安全性和资源控制能力。

总结

通过这篇文章,我们从 /proc 的结构出发,一步步深入了解了它如何连接用户空间与内核空间:

  • /proc/[pid]/ 是每个进程实时的状态镜像,提供了强大的观察与调试能力;
  • /proc/1/ 揭示了 systemd 的诞生过程,以及内核如何启动第一个用户空间进程;
  • /lib/systemd/systemd 本质上是一个功能强大的 ELF 可执行程序,承担整个系统初始化和服务调度任务;
  • /proc 文件系统并非来自磁盘,而是由内核动态生成,与 task_structsysctl 等内核数据结构紧密耦合;
  • 在容器中,/proc 则体现出 Namespace 隔离的魔力,是进程、资源和安全视图隔离的核心接口。

可以说,/proc 不仅是系统调试与监控的重要接口,更是理解 Linux 内核工作方式的重要切入点。它像一面镜子,映照出正在运行的内核机制;也像一扇窗,让我们窥见内核深处的世界。

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

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

相关文章

操作系统(中断 异常 陷阱) ─── linux第28课

目录 1.硬件中断 2. 时钟中断 3. OS本质 4. 软件中断 缺页中断&#xff1f;内存碎片处理&#xff1f;除零野指针错误&#xff1f; 操作系统本质总结 操作系统是对软件硬件资源管理的软件 1.硬件中断 中断向量表(IDT)就是操作系统的⼀部分&#xff0c;启动就加载到内存中了…

文件分片上传

1前端 <inputtype"file"accept".mp4"ref"videoInput"change"handleVideoChange"style"display: none;">2生成hash // 根据整个文件的文件名和大小组合的字符串生成hash值&#xff0c;大概率确定文件的唯一性fhash(f…

机器学习的一百个概念(5)数据增强

前言 本文隶属于专栏《机器学习的一百个概念》&#xff0c;该专栏为笔者原创&#xff0c;引用请注明来源&#xff0c;不足和错误之处请在评论区帮忙指出&#xff0c;谢谢&#xff01; 本专栏目录结构和参考文献请见[《机器学习的一百个概念》 ima 知识库 知识库广场搜索&…

基于微信小程序的智慧乡村旅游服务平台【附源码】

基于微信小程序的智慧乡村旅游服务平台&#xff08;源码L文说明文档&#xff09; 目录 4系统设计 4.1系统功能设计 4.2系统结构 4.3.数据库设计 4.3.1数据库实体 4.3.2数据库设计表 5系统详细实现 5.1 管理员模块的实现 5.1.1旅游景点管理…

数据驱动的智能BMS革新:机器学习赋能电池健康预测与安全协同优化

传统电池管理系统&#xff08;BMS&#xff09;依赖等效电路模型和固定参数算法&#xff0c;面临电化学机理复杂、老化行为非线性、多工况适应性差等瓶颈。例如&#xff0c;健康状态&#xff08;SOH&#xff09;和荷电状态&#xff08;SOC&#xff09;估算易受温度、循环次数及电…

使用JSON.stringify报错:Uncaught TypeError: cyclic object value

具体错误 Uncaught TypeError: cyclic object valueonMouseOver Amap.vue:125renderMarker Amap.vue:84emit maps:1emit maps:1ci maps:1ui maps:1fireEvent maps:1jL maps:1Xt maps:1T maps:1<anonymous> amap.vue:49promise callback*nextTick runtime-core.esm-bundl…

Spring Boot 工程创建详解

2025/4/2 向全栈工程师迈进&#xff01; 一、SpingBoot工程文件的创建 点击Project Structure 然后按着如下点击 最后选择Spring Boot &#xff0c;同时记得选择是Maven和jar&#xff0c;而不是war。因为Boot工程内置了Tomcat&#xff0c;所以不需要war。 紧接着选择Spring We…

Java 8 的流(Stream API)简介

Java 8 引入的 Stream API 是一个强大的工具&#xff0c;用于处理集合&#xff08;如 List、Set&#xff09;中的元素。它支持各种操作&#xff0c;包括过滤、排序、映射等&#xff0c;并且能够以声明式的方式表达复杂的查询操作。流操作可以是中间操作&#xff08;返回流以便进…

4. Flink SQL访问HiveCatalog

一. 实验环境 Flink版本: 1.19.1 Hive版本: 2.1.3 Hadoop版本: 3.2.4二. 操作步骤 1.上传所需的jar包到Flink lib目录下 [roothadoop3 ~]# mv flink-sql-connector-hive-3.1.3_2.12-1.19.1.jar /www/flink-1.19.1/lib [roothadoop3 ~]# mv hadoop-mapreduce-client-core-3.2…

虚拟试衣间-云尚衣橱小程序-衣橱管理实现

衣橱管理实现 目标 (Goal): 用户 (User): 能通过 UniApp 小程序上传衣服图片。 后端 (Backend): 接收图片,存到云存储,并将图片信息(URL、用户ID等)存入数据库。 用户 (User): 能在小程序里看到自己上传的所有衣服图片列表。 技术栈细化 (Refined Tech Stack for this Pha…

HAL库 通过USB Boot进行APP程序升级

硬件&#xff1a;stm32f407VET6芯片&#xff1b; 软件&#xff1a;STM32CubeMx、Keil5 上位机&#xff1a;Dfuse DemoV3.06 这里给出通过在Bootlaoder中使用USB方式来更新APP程序的方法&#xff0c;首先我们编写一个自己的bootloader&#xff0c;关于bootloader的大致原理可以…

数据库权限获取

1. into outfile&#xff08;手写&#xff09; 1.1. 利用条件 • web 目录具有写入权限&#xff0c;能够使用单引号 • 知道网站绝对路径&#xff08;根目录&#xff0c;或则是根目录往下的目录都行&#xff09; • secure_file_priv 没有具体值&#xff08;在 mysql/my.ini…

关于ESP系列MCU的UART download原理

GPIO0&#xff0c;即BOOT&#xff0c;工作模式选择&#xff1a; 悬空/拉高&#xff1a;正常MCU启动工作状态 下拉接地&#xff1a;UARTDownload下载模式 如何进入UARTDownload下载模式&#xff1f; 先按下boot按键不放&#xff0c;再按下rst按键 / en按键&#xff0c;随后释放…

无需安装Office进行 Word、Excel操作的微软开发库

微软的确有一些无需安装完整 Office 就能进行 Word、Excel 操作的开发库&#xff0c;以下为你介绍&#xff1a; 1. Microsoft Graph API 简介&#xff1a;Microsoft Graph API 是一个强大的 RESTful API&#xff0c;能让开发者通过调用接口访问 Office 365 服务里的各种资源&…

【一起来学kubernetes】34、ReplicaSet使用详解

Kubernetes ReplicaSet 使用详解 ReplicaSet 是 Kubernetes 中用于确保指定数量的 Pod 副本持续运行的核心控制器。它通过动态调整 Pod 副本数&#xff0c;保障应用的高可用性和弹性。以下是其核心功能、配置方法及最佳实践&#xff1a; 一、ReplicaSet 核心作用 维持 Pod 副本…

【力扣hot100题】(034)LRU缓存

做完这题已经没有任何力气写链表题了。 思路很简单&#xff0c;就是调试特别的痛苦。 老是频频报错&#xff0c;唉。 class LRUCache { public:struct ListNode{int key,val;ListNode* next; ListNode* prev;ListNode() : key(0), val(0), next(nullptr), prev(nullptr) {}L…

基于随机森林算法的信用风险评估项目

引言 这是一个基于随机森林算法的德国信用风险评估项目&#xff0c;主要目的是构建一个机器学习模型来评估德国客户的信用风险&#xff0c;判断客户是否为高风险客户。 # -*- coding: utf-8 -*- """ 德国信用风险评估随机森林模型 """ # 基础…

亚马逊云科技携手 DeepSeek:开启企业级生成式 AI 新征程

文章目录 一、DeepSeek-R1模型的技术突破&#xff08;一&#xff09;卓越的性能表现&#xff08;二&#xff09;独特的训练方法&#xff08;三&#xff09;丰富的模型生态 二、亚马逊云科技平台上的部署与优化&#xff08;一&#xff09;灵活的部署方式&#xff08;二&#xff…

Windows 实战-evtx 文件分析--笔记

Windows 取证之EVTX日志 - 蚁景网安实验室 - 博客园 一.evtx日志文件是什么 从 Windows NT 6.0&#xff08;也就是 Windows Vista 和 Windows Server 2008&#xff09;开始&#xff0c;微软引入了一种全新的日志文件格式&#xff0c;称为 evtx。这种格式取代了之前 Windows 系…

LangChain/Eliza框架在使用场景上的异同,Eliza通过配置实现功能扩展的例子

LangChain与Eliza框架的异同分析 ‌一、相同点‌ ‌模块化架构设计‌ 两者均采用模块化设计&#xff0c;支持灵活扩展和功能组合。LangChain通过Chains、Agents等组件实现多步骤任务编排‌&#xff0c;Eliza通过插件系统和信任引擎实现智能体功能的动态扩展‌。模块化特性降低…