Linux实现原理 — I/O 处理流程与优化手段

Linux I/O 接口

Linux I/O 接口可以分为以下几种类型:

文件 I/O 接口:用于对文件进行读写操作的接口,包括 open()、read()、write()、close()、lseek() 等。

网络 I/O 接口:用于网络通信的接口,包括 socket()、connect()、bind()、listen()、accept() 等。

设备 I/O 接口:用于对设备(e.g. 字符设备、块设备)进行读写操作的接口,包括 ioctl()、mmap()、select()、poll()、epoll() 等。

其他 I/O 接口:如管道接口、共享内存接口、信号量接口等。

Linux I/O 处理流程

下面以最常用的 read() 和 write() 函数来介绍 Linux 的 I/O 处理流程。

read() 和 write()

read() 和 write() 函数,是最基本的文件 I/O 接口,也可用于在 TCP Socket 中进行数据读写,属于阻塞式 I/O(Blocking I/O),即:如果没有可读数据或者对端的接收缓冲区已满,则函数将一直等待直到有数据可读或者对端缓冲区可写。

函数原型:

fd 参数:指示 fd 文件描述符。

buf 参数:指示 read/write 缓冲区的入口地址。

count 参数:指示 read/write 数据的大小,单位为 Byte。

函数返回值:

  • 返回实际 read/write 的字节数。

  • 返回 0,表示已到达文件末尾。

  • 返回 -1,表示操作失败,可以通过 errno 全局变量来获取具体的错误码。

#include <unistd.h>ssize_t read(int fd, void *buf, size_t count);
ssize_t write(int fd, const void *buf, size_t count);

处理流程

下面以同时涉及了 Storage I/O 和 Network I/O 的一次网络文件下载操作来展开 read() 和 write() 的处理流程。

read() 的处理流程:

  1. Application 调用 read(),CPU 模式从用户态切换到内核态。

  2. Kernel 根据 file fd 查表(进程文件符表),找到对应的 file 结构体(普通文件),从而找到此文件的 inode 编号。

  3. Kernel 将 buf 和 count 参数、以及文件指针位置等信息传递给 Device Driver(磁盘驱动程序)。

  4. Driver 将请求的数据从 Disk Device 中 DMA Copy 到 Kernel PageCache Buffer 中。

  5. Kernel 将数据从 Kernel PageCache Buffer 中 CPU Copy 到 Userspace Buffer 中(Application 不能直接访问 Kernel space)。

  6. read() 最终返回读取的字节数或错误代码给 Application,CPU 模式从内核态切换到用户态。

write() 的处理流程:

  1. Application 调用 write(),CPU 模式从用户态切换到内核态。

  2. Kernel 根据 socket fd 查表,找到对应的 file 结构体(套接字文件),从而找到该 Socket 的 sock 结构体。

  3. Kernel 将 buf 和 count 参数、以及文件指针位置等信息传递给 Device Driver(网卡驱动程序)。

  4. Driver 将请求的数据从 Userspace Buffer 中 CPU Copy 到 Kernel Socket Buffer 中。

  5. Kernel 将数据从 Kernel Socket Buffer 中 DMA Copy 到 NIC Device。

  6. write() 最终返回写入的字节数或错误代码给 Application,CPU 模式从内核态切换到用户态。

可见,在一次常规的 I/O(read/write)操作流程中 处理流程中,总共需要涉及到:

  • 4 次 CPU 模式切换:当 Application 调用 SCI 时,CPU 从用户态切换到内核态;当 SCI 返回时,CPU 从内核态切换回用户态。

  • 2 次 CPU Copy:CPU 执行进程数据拷贝指令,将数据从 User Process 虚拟地址空间 Copy 到 Kernel 虚拟地址空间。

  • 2 次 DMA Copy:CPU 向 DMA 控制器下达设备数据拷贝指令,将数据从 DMA 物理内存空间 Copy 到 Kernel 虚拟地址空间。

相关视频推荐

90分钟搞定底层网络IO模型,linux开发必须要懂得10种模型

手写用户态协议栈以及零拷贝的实现

epoll的原理与使用,epoll比select/poll强在哪里?

免费学习地址:c/c++ linux服务器开发/后台架构师

需要C/C++ Linux服务器架构师学习资料加qun812855908获取(资料包括C/C++,Linux,golang技术,Nginx,ZeroMQ,MySQL,Redis,fastdfs,MongoDB,ZK,流媒体,CDN,P2P,K8S,Docker,TCP/IP,协程,DPDK,ffmpeg等),免费分享

I/O 性能优化机制

I/O buff/cache

Linux Kernel 为了提高 I/O 性能,划分了一部分物理内存空间作为 I/O buff/cache,也就是内核缓冲区。当 Kernel 接收到 read() / write() 等读写请求时,首先会到 buff/cache 查找,如果找到,则立即返回。如果没有则通过驱动程序访问 I/O 外设。

查看 Linux 的 buff/cache:

$ free -mhtotal        used        free      shared  buff/cache   available
Mem:           7.6G        4.2G        2.9G         10M        547M        3.1G
Swap:          4.0G          0B        4.0G

实际上,Cache(缓存)和 Buffer(缓冲)从严格意义上讲是 2 个不同的概念,Cache 侧重加速 “读”,而 Buffer 侧重缓冲 “写”。但在很多场景中,由于读写总是成对存在的,所以并没有严格区分两者,而是使用 buff/cache 来统一描述。

Page Cache

Page Cache(页缓存)是最常用的 I/O Cache 技术,以页为单位的,内容就是磁盘上的物理块,用于减少 Application 对 Storage 的 I/O 操作,能够令 Application 对文件进行顺序读写的速度接近于对内存的读写速度。

页缓存读策略:当 Application 发起一个 Read() 操作,Kernel 首先会检查需要的数据是否在 Page Cache 中:

  • 如果在,则直接从 Page Cache 中读取。

  • 如果不在,则按照原 I/O 路径从磁盘中读取。同时,还会根据局部性原理,进行文件预读,即:将已读数据随后的少数几个页面(通常是三个)一同缓存到 Page Cache 中。

页缓存写策略:当 Application 发起一个 write() 操作,Kernel 首先会将数据写到 Page Cache,然后方法返回,即:Write back(写回)机制,区别于 Write Through(写穿)。此时数据还没有真正的写入到文件中去,Kernel 仅仅将已写入到 Page Cache 的这一个页面标记为 “脏页(Dirty Page)”,并加入到脏页链表中。然后,由 flusher(pdflush,Page Dirty Flush)kernel thread(回写内核线程)周期性地将脏页链表中的页写到磁盘,并清理 “脏页” 标识。在以下 3 种情况下,脏页会被写回磁盘:

  1. 当空闲内存低于一个特定的阈值时,内核必须将脏页写回磁盘,以便释放内存。

  2. 当脏页在内存中驻留时间超过一个特定的阈值时,内核必须将超时的脏页写回磁盘。

  3. 当 Application 主动调用 sync、fsync、fdatasync 等 SCI 时,内核会执行相应的写回操作。

flusher 刷新策略由以下几个内核参数决定(数值单位均为 1/100 秒):

# flush 每隔 5 秒执行一次
$ sysctl vm.dirty_writeback_centisecs
vm.dirty_writeback_centisecs = 500# 内存中驻留 30 秒以上的脏数据将由 flush 在下一次执行时写入磁盘
$ sysctl vm.dirty_expire_centisecs
vm.dirty_expire_centisecs = 3000# 若脏页占总物理内存 10% 以上,则触发 flush 把脏数据写回磁盘
$ sysctl vm.dirty_background_ratio
vm.dirty_background_ratio = 10

综上可见,Page Cache 技术在理想的情况下,可以在一次 Storage I/O 的流程中,减少 2 次 DMA Copy 操作(不直接访问磁盘)。

Buffered I/O

下图展示了一个 C 程序通过 stdio 库中的 printf() 或 fputc() 等输出函数来执行数据写入的操作处理流程。过程中涉及到了多处 I/O Buffer 的实现:

  1. stdio buffer:在 Userspace 实现的 Buffer,因为 SCI 的成本昂贵,所以,Userspace Buffer 用于 “积累“ 到更多的待写入数据,然后再通过一次 SCI 来完成真正的写入。另外,stdio 也支持 fflush() 强制刷新函数。

  2. Kernel buffer cache:处理包括上文以及提到的 Page Cache 技术之外,磁盘设备驱动程序也提供块级别的 Buffer 技术,用于 “积累“ 更多的文件系统元数据和磁盘块数据,然后在合适的时机完成真正的写入。

零拷贝技术(Zero-Copy)

零拷贝技术(Zero-Copy),是通过尽量避免在 I/O 处理流程中使用 CPU Copy 和 DMA Copy 的技术。实际上,零拷贝并非真正做到了没有任何拷贝动作,它更多是一种优化的思想。

下列表格从 CPU Copy 次数、DMA Copy 次数以及 SCI 次数这 3 个方面来对比了几种常见的零拷贝技术。可以看见,2 次 DMA Copy 是不可避免的,因为 DMA 是外设 I/O 的基本行为。零拷贝技术主要从减少 CPU Copy 和 CPU 模式切换这 2 个方面展开。

1、Userspace Direct I/O

Userspace Direct I/O(用户态直接 I/O)技术的底层原理由 Kernel space 中的 ZONE_DMA 支持。ZONE_DMA 是一块 Kernel 和 User Process 都可以直接访问的 I/O 外设 DMA 物理内存空间。基于此, Application 可以直接读写 I/O 外设,而 Kernel 只会辅助执行必要的虚拟存储配置工作,不直接参与数据传输。因此,该技术可以减少 2 次 CPU Copy。

Userspace Direct I/O 的缺点:

  1. 由于旁路了 要求 Kernel buffer cache 优化,就需要 Application 自身实现 Buffer Cache 机制,称为自缓存应用程序,例如:数据库管理系统。

  2. 由于 Application 直接访问 I/O 外设,会导致 CPU 阻塞,浪费 CPU 资源,这个问题需要结合异步 I/O 技术来规避。

具体流程看下图:Using Direct I/O with DMA

2、mmap() + write()

mmap() SCI 用于将 I/O 外设(e.g. 磁盘)中的一个文件、或一段内存空间(e.g. Kernel Buffer Cache)直接映射到 User Process 虚拟地址空间中的 Memory Mapping Segment,然后 User Process 就可以通过指针的方式来直接访问这一段内存,而不必再调用传统的 read() / write() SCI。

申请空间函数原型:

  • addr 参数:分配 MMS 映射区的入口地址,由 Kernel 指定,调用时传入 NULL。

  • length 参数:指示 MMS 映射区的大小。

  • prot 参数:指示 MMS 映射区的权限,可选:PROT_READ、PROT_WRITE、PROT_READ|PROT_WRITE 类型。

  • flags 参数:标志位参数,可选:

  • MAP_SHARED:映射区所做的修改会反映到物理设备(磁盘)上。

  • MAP_PRIVATE:映射区所做的修改不会反映到物理设备上。

  • fd 参数:指示 MMS 映射区的文件描述符。

  • offset 参数:指示映射文件的偏移量,为 4k 的整数倍,可以映射整个文件,也可以只映射一部分内容。

  • 函数返回值:

  • 成功:更新 addr 入口地址。

  • 失败:更新 MAP_FAILED 宏。

void *mmap(void *adrr, size_t length, int prot, int flags, int fd, off_t offset);

释放空间函数原型:

  • addr 参数:分配 MMS 映射区的入口地址,由 Kernel 指定,调用时传入 NULL。

  • length 参数:指示 MMS 映射区的大小。

  • 函数返回值:

  • 成功:返回 0。

  • 失败:返回 -1。

int munmap(void *addr, size_t length)

可见,mmap() 是一种高效的 I/O 方式。通过 mmap() 和 write() 结合的方式,可以实现一定程度的零拷贝优化。

// 读
buf = mmap(diskfd, len);
// 写
write(sockfd, buf, len);

mmap() + write() 的 I/O 处理流程如下。

mmap() 映射:

  1. Application 发起 mmap() 调用,进行文件操作,CPU 模式从用户态切换到内核态。

  2. mmap() 将指定的 Kernel Buffer Cache 空间映射到 Application 虚拟地址空间。

  3. mmap() 返回,CPU 模式从内核态切换到用户态。

  4. 在 Application 后续的文件访问中,如果出现 Page Cache Miss,则触发缺页异常,并执行 Page Cache 机制。通过已经建立好的映射关系,只使用一次 DMA Copy 就将文件数据从磁盘拷贝到 Application User Buffer 中。

write() 写入:

  1. Application 发起 write() 调用,CPU 模式从用户态切换到内核态。

  2. 由于此时 Application User Buffer 和 Kernel Buffer Cache 的数据是一致的,所以直接从 Kernel Buffer Cache 中 CPU Copy 到 Kernel Socket Buffer,并最终从 NIC 发出。

  3. write() 返回,CPU 模式从内核态切换到用户态。

可见,mmap() + write() 的 I/O 处理流程减少了一次 CPU Copy,但没有减少 CPU 模式切换的次数。另外,由于 mmap() 的进程间共享特性,非常适用于共享大文件的 I/O 场景。

mmap() + write() 的缺点:当 mmap 映射一个文件时,如果这个文件被另一个进程所截获,那么 write 系统调用会因为访问非法地址被 SIGBUS 信号终止,SIGBUS 默认会杀死进程并产生一个 coredump。解决这个问题通常需要使用文件租借锁实现。在 mmap 之前加锁,操作完之后解锁。即:首先为文件申请一个租借锁,当其他进程想要截断这个文件时,内核会发送一个实时的 RT_SIGNAL_LEASE 信号,告诉当前进程有进程在试图破坏文件,这样 write 在被 SIGBUS 杀死之前,会被中断,返回已经写入的字节数,并设置 errno 为 success。

3、sendfile()

Linux Kernel 从 v2.1 开始引入了 sendfile(),用于在 Kernel space 中将一个 in_fd 的内容复制到另一个 out_fd 中,数据无需经过 Userspace,所以应用在 I/O 流程中,可以减少一次 CPU Copy。同时,sendfile() 比 mmap() 方式更具安全性。

函数原型:

  • out_fd 参数:目标文件描述符,数据输入文件。

  • in_fd 参数:源文件描述符,数据输出文件。该文件必须是可以 mmap 的。

  • offset 参数:指定从源文件的哪个位置开始读取数据,若不需要指定,传递一个 NULL。

  • count 参数:指定要发送的数据字节数。

  • 函数返回值:

  • 成功:返回复制的字节数。

  • 失败:返回 -1,并设置 errno 全局变量来指示错误类型。

#include <sys/sendfile.h>ssize_t sendfile(int out_fd, int in_fd, off_t *offset, size_t count);

sendfile() 处理流程:

  1. Application 调用 sendfile(),CPU 从用户态切换到内核态。

  2. Kernel 将数据通过 DMA Copy 从磁盘设备写入 Kernel Buffer Cache。

  3. Kernel 将数据从 Kernel Buffer Cache 中 CPU Copy 到 Kernel Socket Buffer。

  4. Kernel 将数据从 Kernel Socket Buffer 中 DMA Copy 到 I/O 网卡设备。

  5. sendfile() 返回,CPU 从内核态切换到用户态。

4、sendfile() + DMA Gather Copy

上文知道 sendfile() 还具有一次 CPU Copy,通过结合 DMA Gather Copy 技术,可以进一步优化它。

DMA Gather Copy 技术,底层有 I/O 外设的 DMA Controller 提供的 Gather 功能支撑,所以又称为 “DMA 硬件辅助的 sendfile()“。借助硬件设备的帮助,在数据从 Kernel Buffer Cache 到 Kernel Socket Buffer 之间,并不会真正的数据拷贝,而是仅拷贝了缓冲区描述符(fd + size)。待完成后,DMA Controller,可以根据这些缓冲区描述符找到依旧存储在 Kernel Buffer Cache 中的数据,并进行 DMA Copy。

显然,DMA Gather Copy 技术依旧是 ZONE_DMA 物理内存空间共享性的一个应用场景。

sendfile() + DMA Gather Copy 的处理流程:

  1. Application 调用 sendfile(),CPU 从用户态切换到内核态模式。

  2. Kernel 将数据通过 DMA Copy 从磁盘设备写入 Kernel Buffer Cache。

  3. Kernel 将数据的缓冲区描述符从 Kernel Buffer Cache 中 CPU Copy 到 Kernel Socket Buffer(几乎不费资源)。

  4. 基于缓冲区描述符,CPU 利用 DMA Controller 的 Gather / Scatter 操作直接批量地将数据从 Kernel Buffer Cache 中 DMA Copy 到网卡设备。

  5. sendfile() 返回,CPU 从内核态切换到用户态。

5、splice()

splice() 与 sendfile() 的处理流程类似,但数据传输方式有本质不同。

  • sendfile() 的传输方式是 CPU Copy,且具有数据大小限制;

  • splice() 的传输方式是 Pipeline,打破了数据范围的限制。但也要求 2 个 fd 中至少有一个必须是管道设备类型。

函数原型:

  • fd_in 参数:源文件描述符,数据输出文件。

  • off_in 参数:输出偏移量指针,表示从源文件描述符的哪个位置开始读取数据。

  • fd_out 参数:目标文件描述符,数据输入文件。

  • off_out 参数:输入偏移量指针,表示从目标文件描述符的哪个位置开始写入数据。

  • len 参数:指示要传输的数据长度。

  • flags:控制数据传输的行为的标志位。

#define _GNU_SOURCE         /* See feature_test_macros(7) */#include <fcntl.h>ssize_t splice(int fd_in, loff_t *off_in, int fd_out, loff_t *off_out, size_t len, unsigned int flags);

splice() 的处理流程如下:

  1. Application 调用 splice(),CPU 从用户态切换到内核态。

  2. Kernel 将数据通过 DMA Copy 从磁盘设备写入 Kernel Buffer Cache。

  3. Kernel 在 Kernel Buffer Cache 和 Kernel Socket Buffer 之间建立 Pipeline 传输。

  4. Kernel 将数据从 Kernel Socket Buffer 中 DMA Copy 到 I/O 网卡设备。

  5. splice() 返回,CPU 从内核态切换到用户态。

6、缓冲区共享技术

缓冲区共享技术,是对 Linux I/O 的一种颠覆,所以往往需要由 Application 和设备来共同实现。

其核心思想是:每个 Applications 都维护着一个 Buffer Pool,并且这个 Buffer Pool 可以同时映射到 Kernel 虚拟地址空间,这样 Userspace 和 Kernel space 就拥有了一块共享的空间。以此来规避掉 CPU Copy 的行为。

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

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

相关文章

buuctf week2-web-ez_sql

闭合之后尝试判断字段数&#xff0c;存在WAF&#xff0c;使用大小写绕过&#xff08;后面的sql语句也需要进行大小写绕过&#xff09; ?id1 Order by 5-- 测出有5列 ?id1 Order by 6-- 查一下数据库名、版本、用户等信息 ?id1Union Select database(),version(),user(),4,…

关于Vue+webpack使用unocss编写CSS,打包后CSS没加前缀

关于Vuewebpack使用unocss编写CSS&#xff0c;打包后CSS没加前缀&#xff0c;封装了一个插件去解决了这个问题 unocss-postcss-webpack-plugin unocss在vite中使用配置&#xff0c;关于unocss在vite中使用&#xff0c;自行查阅官网 https://unocss.dev/integrations/vite ,vi…

最详细STM32,cubeMX 点亮 led

这篇文章将详细介绍 如何在 stm32103 板子上点亮一个LED. 文章目录 前言一、开发环境搭建。二、LED 原理图解读三、什么是 GPIO四、cubeMX 配置工程五、解读 cubeMX 生成的代码六、延时函数七、控制引脚状态函数点亮 LED 八、GPIO 的工作模式九、为什么使用推挽输出驱动 LED总结…

鲲山科技:引入和鲸 ModelWhale,实现量化策略的高效迭代

量化投资是数据科学在金融行业的应用。 2023 年&#xff0c;量化行业的超额收益开始收敛&#xff0c;量化私募如何形成自身核心竞争力&#xff1f; 和鲸拜访客户鲲山科技&#xff08;深圳&#xff09;&#xff0c;揭示其“弯道超车”的独家秘诀。 群体作战 年初至今&#xff…

idea中导入eclipse的javaweb项目——tomact服务(保姆级别)

idea中导入eclipse的javaweb项目——tomact服务&#xff08;保姆级别&#xff09; 1. 导入项目2. Project Settings下的各种配置步骤2.1 检查/修改 jdk 的引入2.2 配置Modules-Dependencies2.2.1 删掉eclipse相关的多余配置2.2.2 删掉jar包2.2.3 添加tomcat的依赖 2.3 配置Libr…

JMeter定时器

一. 同步定时器&#xff08;Synchronizing Timer) &#xff08;在Loadrunner中叫做集合点&#xff09; 思考&#xff1a; 如何模拟多个用户同时抢一个红包&#xff1f;如何测试电商网站中抢购活动、秒杀活动&#xff1f; 1.1 介绍 Sync Timer的目的是阻塞线程&#xff0c;直…

云原生SIEM解决方案

云原生&#xff08;Cloud Native&#xff09;是一种基于云计算的软件开发和部署方法论&#xff0c;它强调将应用程序和服务设计为云环境下的原生应用&#xff0c;以实现高可用性、可扩展性和灵活性。 云原生的优势有哪些 高可用性&#xff1a;云原生可以实现应用程序的高可用…

分享一下便利店怎么做微信小程序

便利店微信小程序开发&#xff0c;让生意更便捷&#xff01; 在这个数字化时代&#xff0c;微信小程序已经成为一种新的生活方式。它不仅改变了人们的消费习惯&#xff0c;还为各行各业提供了无限商机。对于便利店来说&#xff0c;微信小程序是一个绝佳的营销工具&#xff0c;…

汉诺塔问题

汉诺塔问题 本文部分截图来源&#xff1a;汉诺塔可视化小游戏 移动最终目标&#xff1a;将A柱中的所有盘移动至C柱 移动过程要求&#xff1a;1.每次只能移动一个盘 2.每次移动后必须保证小盘在大盘上方 问题简化 我们先将三个盘&#xff08;n-1&#xff0c;n4&#xff09;看作…

微信小程序clearInterval无法关闭时间间隔器问题解决

今天在微信小程序遇到了一个问题 我的代码是这样的 // 关闭动画函数 AnimationOff() {//定义时间间隔器clearInterval(this.animationTimer) }, DefineAnimation() {//定义时间间隔器this.animationTimer setInterval(() > {console.log("执行");}, 1000) },但是…

C++ - git 命令行

为什么要有 git 你很可能遇到过这种情况&#xff0c;在写项目的时候&#xff0c;要我不符合 leader 的要求&#xff0c;因而修改了很多个版本&#xff0c;但是修改到最后一版的时候&#xff0c;leader 有觉得当前这版还没有之前 某一版好&#xff0c;现在又要求你在 之前的那一…

MyBatis基础之自动映射、映射类型、文件注解双配置

文章目录 自动映射原理jdbcType同时启用配置文件和注解两种配置方式 自动映射原理 在 MyBatis 的配置文件&#xff08;settings 元素部分&#xff09;中&#xff0c;有一个 autoMappingBehavior 配置&#xff0c;其默认值为 PARTIAL &#xff0c;表示 MyBatis 会自动映射&…

Spring实战 | Spring AOP核心秘笈之葵花宝典

Spring实战系列文章&#xff1a; Spring实战 | Spring IOC不能说的秘密&#xff1f; 国庆中秋特辑系列文章&#xff1a; 国庆中秋特辑&#xff08;八&#xff09;Spring Boot项目如何使用JPA 国庆中秋特辑&#xff08;七&#xff09;Java软件工程师常见20道编程面试题 国庆…

SpringBoot日志文件

目录 日志级别 设置日志级别 日志持久化 获取日志的两种方式 1.LoggerFactory.getLogger(类名.class) 2. lombok的slf4j注解和log对象 日志级别 由低到高依次是&#xff1a;trace->debug->info->warn->error->fatal 其中当程序里设置了日志级别后&#xff0c;程…

实验3:左右循环LED灯

获取流水灯工程&#xff1a; 方式一&#xff1a; keilproteus 完成最小系统&#xff0c;点亮led 灯实验_吴小凹的博客-CSDN博客 方式二&#xff1a; Flowing_led.zip - 蓝奏云直接下载。 原理图修改&#xff1a; 无须修改只需要使用流水灯的工程即可&#xff0c;解压到桌面…

记一次Hbase2.1.x历史数据数据迁移方案

查看待迁移的表 list_namespace_tables vaas_dwm2. 制作待迁移表“DWM_TRIP_PART”的快照 snapshot vaas_dwm:DWM_TRIP_PART,dwm_trip_part_snapshot3. 统计待迁移表数据总数 hbase org.apache.hadoop.hbase.mapreduce.RowCounter vaas_dwm:DWM_TRIP_PART

人脸活体检测技术的应用,有效避免人脸识别容易被攻击的缺陷

随着软件算法和物理终端的进步&#xff0c;人脸识别现在越来越被广泛运用到生活的方方面面&#xff0c;已经成为了重要的身份验证手段&#xff0c;但同时也存在着自身的缺陷&#xff0c;目前常规人脸识别技术可以精准识别目标人像特征&#xff0c;并迅速返回比对结果&#xff0…

ADAS可视化系统,让自动驾驶更简单 -- 入门篇

随着车载芯片的升级、技术的更新迭代&#xff0c;可视化ADAS逐渐变成汽车的标配走入大家的生活中&#xff0c;为大家的驾车出行带来切实的便捷。那么你了解HMI端ADAS的实现过程吗&#xff1f;作为ADAS可视化系统的入门篇&#xff0c;就跟大家聊一聊目前较常见的低消耗的一种ADA…

LLM应用架构 LLM application architectures

在本课程的最后一部分&#xff0c;您将探讨构建基于LLM的应用程序的一些额外考虑因素。首先&#xff0c;让我们把迄今为止在本课程中所见的一切汇总起来&#xff0c;看看创建LLM驱动应用程序的基本组成部分。您需要几个关键组件来创建端到端的应用程序解决方案&#xff0c;从基…

【学习笔记】minIO分布式文件服务系统

MinIO 一、概述 1.1 minIO是什么&#xff1f; MinIO是专门为海量数据存储、人工智能、大数据分析而设计的对象存储系统。&#xff08;早前流行的还有FastDFS&#xff09; 据官方介绍&#xff0c;单个对象最大可存储5T&#xff0c;非常适合存储海量图片、视频、日志文件、备…