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

二、BIO、NIO编程与直接内存、零拷贝

一、网络通信

        1、什么是socket?


                Socket 是应用层与 TCP/IP 协议族通信的中间软件抽象层,它是一组接口,一般由操作
系统提供。客户端连接上一个服务端,就会在客户端中产生一个 socket 接口实例,服务端每接受
一个客户端连接,就会产生一个 socket 接口实例和客户端的 socket 进行通信,有多个客户
端连接自然就有多个 socket 接口实例。

        

2、网络编程中的serversocket与socket

在网络编程中,应用程序启动会使用serversocket监听端口,客户端通过ip与端口找到对应的应用程序;建立连接后应用程序会创建对应的socket读取客户端传输的数据,并通过socket写入数据后返回给客户端;

二、JDK中的BIO

        BIO中的serversocket负责绑定IP,启动监听端口,等待客户端链接;客户端的Socket实例发起链接操作,serversocket接收后产生一个新的服务端socket负责与客户端实例通过输入流和输出流进行通信;

        阻塞体现:1、服务启动就绪,主线程一直等待客户端链接,主线程阻塞;

                          2、建立连接后,在读取socket信息之前,线程也是一直阻塞等待;

传统BIO模型

当客户端访问数量增加,线程与客户端访问数量1:1,服务端会创建大量线程,线程数量增加,系统性能急剧下降,过多会导致系统宕机;

为了改进这一问题,我们可以采用n个线程处理多个客户端请求,这一方式会导致多个客户端等待,这是最大的弊端;

三、什么是NIO?

NIO是为了弥补BIO的不足,提供了高速的、面向块的I/O。NIO全称NO-Blocking io;

Java NIO 和 IO 之间第一个最大的区别是,IO 是面向流的,NIO 是面向缓冲区的。 Java IO
面向流意味着每次从流中读一个或多个字节,直至读取所有字节,它们没有被缓存在任何地
方。此外,它不能前后移动流中的数据。如果需要前后移动从流中读取的数据,需要先将它
缓存到一个缓冲区。 Java NIO 的缓冲导向方法略有不同。数据读取到一个它稍后处理的缓
冲区,需要时可在缓冲区中前后移动。这就增加了处理过程中的灵活性。但是,还需要检查
是否该缓冲区中包含所有需要处理的数据。而且,需确保当更多的数据读入缓冲区时,不要
覆盖缓冲区里尚未处理的数据。

1、阻塞与非阻塞IO

java IO的各种流是阻塞的,这意味着当一个线程调用read()或write时,该线程被阻塞;

java NIO的非阻塞模式,使一个线程从某通道发送请求读取数据使他仅能得到目前可用的数据,如果没有数据就什么都读取不到;而不是保持阻塞,所以直到数据变更前,可以做其它的事情,因此是非阻塞;

2、NIO之Reactor(反应器)模式

“反应”即“倒置”,“控制逆转”,具体事件处理程序不调用反应器;而向反应器注册一个事件处理器,表示自己对某些事件感兴趣,有事件来了,具体事件处理程序通过事件处理器对某个指定的事件发生做出反应;这种控制逆转又称为“好莱坞法则”(不要调用我,让我来调用你)

3、NIO的三大组件

        Selector选择器、channel管道、buffer缓冲区;

Channels:管道,通道,应用程序与操作系统交互事件与传递内容的渠道(应用程序可以通过通道来读写数据);

        a、所有被Selector注册的通道,只能是继承了SelectableChannel类的子类;

        b、ServerSocketChannel:应用程序的监听的通道,只有通过这个通道,应用程序才能向操作系统注册支持多路复用IO的端口监听;        

        c、SocketChannel:TCP Socket套接字的监听通道,一个socket套接字对应了一个客户端IP:端口,服务端ip:端口;

Selector:java的NIO选择器允许一个单独的线程来监视多个输入通道,即多个通道可以使用一个选择器;这个单独的线程可以操作这个选择器选择通道;这种机制可以是的一个单独的线程很容易来管理多个通道;

应用程序会向selector注册需要它关注的channel,以及具体的channel会对哪些IO事件感兴趣;

Buffer:缓冲区,用于和NIO通道进行交互,数据从通道读入缓冲区,从缓冲区写入通道中;(本质是一块可以写入数据,读取数据的内存);就是包装成了NIO Buffer对象,封装了该内存的访问方法;

// 创建选择器
Selector Selector=Selector.open();
// 打开监听通道
serverChannel = ServerSocketChannel.open();
// 开启非阻塞模式
serverChannel.configureBlcok(false);
// 绑定端口 backlog设为1024
serverChannel.socket.bind(new InetSocketAddress(port),1024);
// 注册监听,监听客户端连接请求 SelectionKey.OP_READ(读事件) SelectionKey.OP_WRITE(写事件)
SelectionKey key= channel.register(selector,SelectionKey.OP_READ);

4、什么是SelectionKey?

        SelectionKey是一个抽象类,表示 selectableChannel 在 Selector 中注册的标识.每个 Channel
向 Selector 注册时,都将会创建一个 SelectionKey。SelectionKey 将 Channel 与 Selector 建立了
关系,并维护了 channel 事件。

SelectionKey的类型

操作类型就绪条件及说明
OP_READ(读)当操作系统读缓冲区有数据可读时就绪。并非时刻都有数据可读,所以一般需要注册该操作,仅当有就绪时才发起读操作,有的放矢,避免浪费 CPU。
OP_WRITE(写)当操作系统写缓冲区有空闲空间时就绪。一般情况下写缓冲区都有空闲空间,小块数据直接写入即可,没必要注册该操作类型,否则该条件不断就绪浪费 CPU;但如果是写密集型的任务,比如文件下载等,缓冲区很可能满,注册
该操作类型就很有必要,同时注意写完后取消注册。
OP_CONNECT(请求连接)当 SocketChannel.connect()请求连接成功后就绪。该操作只给客户端使用。
OP_ACCEPT(接受连接)当接收到一个客户端连接请求时就绪。该操作只给服务器使用。

服务端与客户端感兴趣的类型

OP_READOP_WRITEOP_CONNECTOP_ACCEPT
服务器 ServerSocketChannel
服务器 SocketChanne
客户端 SocketChannel

服务器启动 ServerSocketChannel,关注 OP_ACCEPT 事件,
客户端启动 SocketChannel,连接服务器,关注 OP_CONNECT 事件
服务器接受连接,启动一个服务器的 SocketChannel,这个 SocketChannel 可以关注
OP_READ、OP_WRITE 事件,一般连接建立后会直接关注 OP_READ 事件
客户端这边的客户端 SocketChannel 发现连接建立后,可以关注 OP_READ、OP_WRITE
事件,一般是需要客户端需要发送数据了才关注 OP_READ 事件
连接建立后客户端与服务器端开始相互发送消息(读写),根据实际情况来关注 OP_READ、
OP_WRITE 事件。

5、Buffer中的概念

        capactiy:Buffer内存块固定的大小值成为capactiy;只能往里面写byte、long、char等类型;buffer满了需要将其清空才能继续往里面写数据;

        position:表示当前能写以及可读的位置;

        limit:写模式下limit表示最多能写多少数据,等于capacity;

                  读模式下,表示最多能读多少数据,读模式下limit等于写模式下的position;

        Buffer的分配:想要获得一个buffer首先要进行分配,可以在堆上分配,也可以在直接内存;

6、直接内存

        直接内存不是运行在虚拟机的数据区,也不是java定义的内存区域,是系统的内存区域;

NIO可以使用Native函数直接分配堆外内存,然后通过一个存储在java堆里的DirectByteBuffer对象作为这块内存的引用进行操作;可以避免java堆与Natice堆中来回复制数据;

直接内存的申请更加耗费性能,但读写性能要优于普通堆内存;

7、Reactor模式类型

        单线程Reactor模式流程

a、服务器端的 Reactor 是一个线程对象,该线程会启动事件循环,并使用 Selector(选择器)来实现 IO 的多路复用。注册一个 Acceptor 事件处理器到 Reactor 中,Acceptor 事件处理器所关注的事件是 ACCEPT 事件,这样 Reactor 会监听客户端向服务器端发起的连接请求事件(ACCEPT 事件)。

b、客户端向服务器端发起一个连接请求,Reactor 监听到了该 ACCEPT 事件的发生并将该 ACCEPT 事件派发给相应的 Acceptor 处理器来进行处理。Acceptor 处理器通过 accept()方法得到与这个客户端对应的连接(SocketChannel),然后将该连接所关注的 READ 事件以及对应的 READ 事件处理器注册到 Reactor 中,这样一来 Reactor 就会监听该连接的 READ 事件了。

c、当 Reactor 监听到有读或者写事件发生时,将相关的事件派发给对应的处理器进行处理。比如,读处理器会通过 SocketChannel 的 read()方法读取数据,此时 read()操作可以直接读取到数据,而不会堵塞与等待可读的数据到来。

d、每当处理完所有就绪的感兴趣的 I/O 事件后,Reactor 线程会再次执行 select()阻塞等待新的事件就绪并将其分派给对应处理器进行处理。

注意,Reactor 的单线程模式的单线程主要是针对于 I/O 操作而言,也就是所有的 I/O 的
accept()、read()、write()以及 connect()操作都在一个线程上完成的。

但在目前的单线程 Reactor 模式中,不仅 I/O 操作在该 Reactor 线程上,连非 I/O 的业务
操作也在该线程上进行处理了,这可能会大大延迟 I/O 请求的响应。所以我们应该将非 I/O
的业务逻辑操作从 Reactor 线程上卸载,以此来加速 Reactor 线程对 I/O 请求的响应。

单线程Reactor,工作者线程池

与单线程 Reactor 模式不同的是,添加了一个工作者线程池,并将非 I/O 操作从 Reactor线程中移出转交给工作者线程池来执行。这样能够提高 Reactor 线程的 I/O 响应,不至于因为一些耗时的业务逻辑而延迟对后面 I/O 请求的处理。

优势:a、线程重复利用

           b、核心线程提前创建好,不用等待线程创建

           c、线程池大小可以调节,更好的利用处理器

多线程主从Reactor模式

Reactor 线程池中的每一 Reactor 线程都会有自己的 Selector、线程和分发的事件循环逻
辑。mainReactor 可以只有一个,但 subReactor 一般会有多个。mainReactor 线程主要负责接
收客户端的连接请求,然后将接收到的 SocketChannel 传递给 subReactor,由 subReactor 来
完成和客户端的通信。

a、注册一个 Acceptor 事件处理器到 mainReactor 中,Acceptor 事件处理器所关注的事件是 ACCEPT 事件,这样 mainReactor 会监听客户端向服务器端发起的连接请求事件(ACCEPT
事件)。启动 mainReactor 的事件循环。
b、 客户端向服务器端发起一个连接请求,mainReactor 监听到了该 ACCEPT 事件并将ACCEPT 事件派发给 Acceptor 处理器来进行处理。Acceptor 处理器通过 accept()方法得到与这个客户端对应的连接(SocketChannel),然后将这个 SocketChannel 传递给 subReactor 线程池。
c、 subReactor 线程池分配一个 subReactor 线程给这个 SocketChannel,即将SocketChannel 关注的 READ 事件以及对应的 READ 事件处理器注册到 subReactor 线程中。当然你也注册 WRITE 事件以及 WRITE 事件处理器到 subReactor 线程中以完成 I/O 写操作。Reactor 线程池中的每一 Reactor 线程都会有自己的 Selector、线程和分发的循环逻辑。
d、 当有 I/O 事件就绪时,相关的 subReactor 就将事件派发给响应的处理器处理。注意,这里 subReactor 线程只负责完成 I/O 的 read()操作,在读取到数据后将业务逻辑的处理放入到线程池中完成,若完成业务逻辑后需要返回数据给客户端,则相关的 I/O 的 write 操作还是会被提交回 subReactor 线程来完成。

四、零拷贝

        1、什么是零拷贝?

        零拷贝是指计算机执行操作时,cpu不需要先将数据复制到另一个特定区域。为了网络传输文件时节省cpu周期和内存宽带;

        零拷贝技术可以减少数据拷贝和共享总线操作的次数,消除传输数据在存储器之间的不必要的中间拷贝次数,从而提高数据传输效率;

        零拷贝技术减少了用户进程地址空间和内核地址空间之间因为上下文切换带来的开销;

        所以零拷贝只是说减少冗余的拷贝;

        下面这些组件、框架中均使用了零拷贝技术:Kafka、Netty、Rocketmq、Nginx、Apache。

        2、linux的I/O机制与DMA

                早期用户进程读取磁盘数据,需要CPU中断和CPU参与,每次中断都会带来CPU的上下文切换;

                DMA(Diect Memory Access,直接内存存取),他允许不同速度的硬件装置来沟通,不需要以来CPU的大量中断负载;

                DMA控制器,接管了数据读写请求,减少CPU负担,现代硬盘基本都支持DMA;

                现在的IO读取的过程

                        a、DMA等待数据准备好,把磁盘数据读取到操作系统的内核缓冲区;

                        b、用户进程,将内存缓冲区的数据copy到用户空间;

                传统数据传统过程

                        a、将磁盘文件读取到操作系统内核缓冲区;

                        b、将内核缓冲区的数据copy到应用程序的buffer;

                        c、应用程序将buffer中的数据copy到socket网络发送缓冲区;

                        d、将socket buffer的数据copy到网卡;再有网卡进行网络传输;

上述四次copy中第二次和第三次没有什么帮助,反而浪费了系统资源;

3、linux中支持的零拷贝

        mmap内存映射

         硬盘上文件的位置和应用程序缓冲区进行映射,由于mmap将文件直接映射到用户空间,所以实际文件读取根据这个映射直接将文件从硬盘copy到用户空间,减少数据copy到内核缓冲空间;

mmap 内存映射将会经历:3 次拷贝: 1 次 cpu copy,2 次 DMA copy;
以及 4 次上下文切换,调用 mmap 函数 2 次,write 函数 2 次。

sendfile

        linux2.1支持的sendfile

        当调用sendfile()时,DMA将磁盘数据复制到kernel buffer,然后将数据直接copy到socket buffer,数据并未真正复制到socket的buffer,只将数据的位置和长度等描述复制到socket buffer中;DMA将数据从内核缓冲区中直接传递给协议引擎,消除遗留的最后一次复制;(这个需要DMA设备支持才行)

sendfile 会经历:3(2,如果硬件设备支持)次拷贝,1(0,,如果硬件设备支持)次
CPU copy, 2 次 DMA copy;以及 2 次上下文切换

splice

        linux从2.6.17支持splice

        数据从磁盘读取到OS内核缓冲区后,在内核缓冲区直接转成内核空间其它数据bufffer,从而不需要copy到用户空间;

和 sendfile()不同的是,splice()不需要硬件支持

splice 会经历 2 次拷贝: 0 次 cpu copy 2 次 DMA copy;以及 2 次上下文切换

所以最终linux中的零拷贝是DMAcopy了一次,cpu的零拷贝;

4、java中的零拷贝

        java中的仅支持两种(mmap,sendfile);

NIO提供的内存映射MappedByteBuffer

        NIO 中的 FileChannel.map()方法其实就是采用了操作系统中的内存映射方式,底层就是调用 Linux mmap()实现的。将内核缓冲区的内存和用户缓冲区的内存做了一个地址映射。这种方式适合读取大文件,同时也能对文件内容进行更改,但是如果其后要通过 SocketChannel 发送,还是需要 CPU 进行数据的拷贝。

NIO提供的sendfile

        NIO 中的 FileChannel.map()方法其实就是采用了操作系统中的内存映射方式,底层就是调用 Linux mmap()实现的。将内核缓冲区的内存和用户缓冲区的内存做了一个地址映射。这种方式适合读取大文件,同时也能对文件内容进行更改,但是如果其后要通过 SocketChannel 发送,还是需要 CPU 进行数据的拷贝。

相关文章:

二、BIO、NIO编程与直接内存、零拷贝

一、网络通信 1、什么是socket? Socket 是应用层与 TCP/IP 协议族通信的中间软件抽象层,它是一组接口,一般由操作 系统提供。客户端连接上一个服务端,就会在客户端中产生一个 socket 接口实例,服务端每接受 一个客户端…...

VSCode 更好用的设置

配置 {"terminal.integrated.fontSize": 15,"security.workspace.trust.untrustedFiles": "open","editor.minimap.enabled": false,"workbench.colorTheme": "Visual Studio 2017 Light - C","gnuGlobal.c…...

【git】-3 github创建远程仓库,上传自己的项目,下载别人的项目

一、如何使用Github 1、创建远程仓库 2、使用github拉取/推送代码 克隆仓库 向远程仓库推送代码-git push 二、上传我们自己的项目到github 方法一:直接上传 方法二:使用git命令 方法三: 将仓库拉取到本地上传 三、下载别人的项目 …...

计算机组成原理(1)

系统概述 计算机硬件基本组成早期冯诺依曼机现代计算机 计算机各部分工作原理主存储器运算器控制器计算机工作过程 此文章的图片资源获取来自于王道考研 计算机硬件基本组成 早期冯诺依曼机 存储程序是指将指令以二进制的形式事先输入到计算机的主存储器,然后按照…...

Openstack网络组件之Neutron

从Nova到Neutron:OpenStack网络架构的演变 在云计算和虚拟化技术迅猛发展的背景下,OpenStack 成为了构建私有云和公有云平台的首选解决方案之一。早期版本中,Nova 项目不仅负责计算资源的管理,还承担了提供基本网络连接的任务。然…...

神州数码交换机和路由器命令总结

神州数码交换机和路由器命令总结 一、神州数码交换机命令总结 1. 交换机恢复出厂设置及其基本配置. 1) //进入特权模式 2) del startup.cfg 2. Telnet方式管理交换机. 1) //进入全局配置模式 2) enable password 0 [密码] 3) Line 0 4 4) Password 0 [密码] 5) Login 3. 交换机…...

Spring MVC简单数据绑定

【图书介绍】《SpringSpring MVCMyBatis从零开始学(视频教学版)(第3版)》_springspringmvcmybatis从零开始 代码、课件、教学视频与相关软件包下载-CSDN博客 《SpringSpring MVCMyBatis从零开始学(视频教学版)(第3版&…...

《SQL ORDER BY》

《SQL ORDER BY》 介绍 SQL(Structured Query Language)是一种用于管理关系数据库管理系统的标准编程语言。ORDER BY语句是SQL中的一个重要部分,它用于对查询结果进行排序。在本篇文章中,我们将详细介绍SQL ORDER BY语句的用法、语法、示例以及一些高级应用。 语法 ORD…...

RabbitMQ基础(简单易懂)

RabbitMQ高级篇请看: RabbitMQ高级篇-CSDN博客 目录 什么是RabbitMQ? MQ 的核心概念 1. RabbitMQ 的核心组件 2. Exchange 的类型 3. 数据流向说明 如何安装RabbitQueue? WorkQueue(工作队列): Fa…...

DNS解析域名简记

域名通常是由: 权威域名.顶级域名.根域名组成的。 从左往右,级别依次升高,这和外国人从小范围到大范围的说话习惯相关。(我们自己是更习惯先说大范围再说小范围,如XX省XX市XX区XX路) DNS解析域名时,会先查…...

【2024年华为OD机试】(B卷,100分)- 求最小步数 (Java JS PythonC/C++)

一、问题描述 题目描述 求从坐标零点到坐标点 n 的最小步数&#xff0c;一次只能沿横坐标轴向左或向右移动 2 或 3。 注意&#xff1a;途径的坐标点可以为负数。 输入描述 坐标点 n 输出描述 输出从坐标零点移动到坐标点 n 的最小步数。 备注 1 < n < 10^9 用例…...

<C++> XlsxWriter写EXCEL

XlsxWriter XlsxWriter是一个用于创建和写入Excel 2007及以上版本&#xff08;.xlsx文件格式&#xff09;的C库。以下是对XlsxWriter的详细介绍&#xff1a; 主要功能 文本、数字和公式写入&#xff1a;可以向多个工作表中写入文本、数字和公式。格式设置&#xff1a;支持丰…...

接上一主题,实现QtByteArray任意进制字符串转为十进制数

函数&#xff1a; /// <summary>/// n进制字符串转为十进制数&#xff0c;snDefine的长度最小为二进制数。/// 例子&#xff1a;/// _pn(_Math::strNToInt(_t("1010"), _t("01")));/// _pn(_Math::strNToInt(_t("-1010"), _t("0123…...

CNN-GRU-MATT加入贝叶斯超参数优化,多输入单输出回归模型

CNN-GRU-MATT加入贝叶斯超参数优化&#xff0c;多输入单输出回归模型 目录 CNN-GRU-MATT加入贝叶斯超参数优化&#xff0c;多输入单输出回归模型预测效果基本介绍程序设计参考资料 预测效果 基本介绍 1.Matlab实现贝叶斯优化CNN-GRU融合多头注意力机制多变量回归预测&#xff…...

Java 如何传参xml调用接口获取数据

传参和返参的效果图如下&#xff1a; 传参&#xff1a; 返参&#xff1a; 代码实现&#xff1a; 1、最外层类 /*** 外层DATA类*/ XmlRootElement(name "DATA") public class PointsXmlData {private int rltFlag;private int failType;private String failMemo;p…...

uniapp 之 uni-forms校验提示【提交的字段[‘xxx‘]在数据库中并不存在】解决方案

目录 场景问题代码结果问题剖析解决方案 场景 uni-forms官方组件地址 使用uniapp官方提供的组件&#xff0c;某个表单需求&#xff0c;单位性质字段如果是高校&#xff0c;那么工作单位则是高校的下拉选择格式&#xff0c;单位性质如果是其他的类型&#xff0c;工作单位则是手动…...

excel VBA 基础教程

这里写目录标题 快捷键选择所有有内容的地方 调试VBA录制宏&#xff0c;打开VBA开发工具录制宏,相当于excel自动写代码&#xff08;两个表格内容完全一致才可以&#xff09; 查看宏代码保持含有宏程序的文件xlsm后缀&#xff08;注意很容易有病毒&#xff09;宏文件安全设置 使…...

基于异步IO的io_uring

基于异步IO的io_uring 1. io_uring的实现原理 io_uring使用了一种异步IO机制&#xff0c;它通过一对环形缓冲区(ring buffer)实现用户态于内核态之间的高效通信&#xff0c;用户只需将IO请求放入提交队列&#xff0c;当内核完成IO请求时&#xff0c;会将结果放入完成队列&…...

【江协STM32】10-2/3 MPU6050简介、软件I2C读写MPU6050

1. MPU6050简介 MPU6050是一个6轴姿态传感器&#xff0c;可以测量芯片自身X、Y、Z轴的加速度、角速度参数&#xff0c;通过数据融合&#xff0c;可进一步得到姿态角&#xff0c;常应用于平衡车、飞行器等需要检测自身姿态的场景3轴加速度计&#xff08;Accelerometer&#xff…...

仓颉笔记——写一个简易的web服务并用浏览器打开

创建一个web服务端&#xff0c;同时创建一个客户端去读取这个服务端。 也满足浏览器打开web的需求。 直接上代码。 import net.http.* import std.time.* import std.sync.* import std.log.LogLevel// 1. 构建 Server 实例 let server ServerBuilder().addr("127.0.0.1&…...

web vue 项目 Docker化部署

Web 项目 Docker 化部署详细教程 目录 Web 项目 Docker 化部署概述Dockerfile 详解 构建阶段生产阶段 构建和运行 Docker 镜像 1. Web 项目 Docker 化部署概述 Docker 化部署的主要步骤分为以下几个阶段&#xff1a; 构建阶段&#xff08;Build Stage&#xff09;&#xff1a…...

Swift 协议扩展精进之路:解决 CoreData 托管实体子类的类型不匹配问题(下)

概述 在 Swift 开发语言中&#xff0c;各位秃头小码农们可以充分利用语法本身所带来的便利去劈荆斩棘。我们还可以恣意利用泛型、协议关联类型和协议扩展来进一步简化和优化我们复杂的代码需求。 不过&#xff0c;在涉及到多个子类派生于基类进行多态模拟的场景下&#xff0c;…...

Mac软件卸载指南,简单易懂!

刚和Adobe分手&#xff0c;它却总在Library里给你写"回忆录"&#xff1f;卸载的Final Cut Pro像电子幽灵般阴魂不散&#xff1f;总是会有残留文件&#xff0c;别慌&#xff01;这份Mac软件卸载指南&#xff0c;将用最硬核的方式教你"数字分手术"&#xff0…...

QT: `long long` 类型转换为 `QString` 2025.6.5

在 Qt 中&#xff0c;将 long long 类型转换为 QString 可以通过以下两种常用方法实现&#xff1a; 方法 1&#xff1a;使用 QString::number() 直接调用 QString 的静态方法 number()&#xff0c;将数值转换为字符串&#xff1a; long long value 1234567890123456789LL; …...

GC1808高性能24位立体声音频ADC芯片解析

1. 芯片概述 GC1808是一款24位立体声音频模数转换器&#xff08;ADC&#xff09;&#xff0c;支持8kHz~96kHz采样率&#xff0c;集成Δ-Σ调制器、数字抗混叠滤波器和高通滤波器&#xff0c;适用于高保真音频采集场景。 2. 核心特性 高精度&#xff1a;24位分辨率&#xff0c…...

Xen Server服务器释放磁盘空间

disk.sh #!/bin/bashcd /run/sr-mount/e54f0646-ae11-0457-b64f-eba4673b824c # 全部虚拟机物理磁盘文件存储 a$(ls -l | awk {print $NF} | cut -d. -f1) # 使用中的虚拟机物理磁盘文件 b$(xe vm-disk-list --multiple | grep uuid | awk {print $NF})printf "%s\n"…...

Linux离线(zip方式)安装docker

目录 基础信息操作系统信息docker信息 安装实例安装步骤示例 遇到的问题问题1&#xff1a;修改默认工作路径启动失败问题2 找不到对应组 基础信息 操作系统信息 OS版本&#xff1a;CentOS 7 64位 内核版本&#xff1a;3.10.0 相关命令&#xff1a; uname -rcat /etc/os-rele…...

如何更改默认 Crontab 编辑器 ?

在 Linux 领域中&#xff0c;crontab 是您可能经常遇到的一个术语。这个实用程序在类 unix 操作系统上可用&#xff0c;用于调度在预定义时间和间隔自动执行的任务。这对管理员和高级用户非常有益&#xff0c;允许他们自动执行各种系统任务。 编辑 Crontab 文件通常使用文本编…...

【Linux系统】Linux环境变量:系统配置的隐形指挥官

。# Linux系列 文章目录 前言一、环境变量的概念二、常见的环境变量三、环境变量特点及其相关指令3.1 环境变量的全局性3.2、环境变量的生命周期 四、环境变量的组织方式五、C语言对环境变量的操作5.1 设置环境变量&#xff1a;setenv5.2 删除环境变量:unsetenv5.3 遍历所有环境…...

Chromium 136 编译指南 Windows篇:depot_tools 配置与源码获取(二)

引言 工欲善其事&#xff0c;必先利其器。在完成了 Visual Studio 2022 和 Windows SDK 的安装后&#xff0c;我们即将接触到 Chromium 开发生态中最核心的工具——depot_tools。这个由 Google 精心打造的工具集&#xff0c;就像是连接开发者与 Chromium 庞大代码库的智能桥梁…...