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

Linux高级IO

高级IO

  • 1.五种IO模型
    • 1.1 阻塞IO
    • 1.2 非阻塞IO
    • 1.3 信号驱动IO
    • 1.4 多路复用/多路转接IO
    • 1.5 异步IO
    • 1.6 小结
  • 2.高级IO重要概念
  • 3.非阻塞IO
    • 3.1 实现函数NoBlock
    • 3.2 轮询方式读取标准输入
  • 4.I/O多路转接之select
    • 4.1 理解select执行过程
    • 4.2 select的特点
    • 4.3 select缺点
    • 4.4 实现
  • 5.I/O多路转接之poll
    • 5.1 poll函数
    • 5.2 poll的优点
    • 5.3 poll的缺点
    • 5.4 实现
  • 6.I/O多路转接之epoll
    • 6.1 epoll的相关系统调用
    • 6.2 epoll工作原理
    • 6.3 epoll的优点(和 select 的缺点对应)
    • 6.4 epoll工作方式
    • 6.5 对比LT和ET
    • 6.6 实现

🌟🌟hello,各位读者大大们你们好呀🌟🌟
🚀🚀系列专栏:【Linux的学习】
📝📝本篇内容:五种IO模型;高级IO重要概念;非阻塞IO;I/O多路转接之select;I/O多路转接之poll;I/O多路转接之epoll
⬆⬆⬆⬆上一篇:网络基础(三)
💖💖作者简介:轩情吖,请多多指教(>> •̀֊•́ ) ̖́-

1.五种IO模型

其实我们之前的使用的IO就是调用系统调用,但是讲的更加详细一点就是IO=等待+数据拷贝,我们进行IO是有条件的,比如write的时候要有空间,read的时候要有数据,达成这种条件就叫做IO事件就绪
高效的IO就是单位时间,等待的比重越低,效率越高

1.1 阻塞IO

阻塞IO: 在内核将数据准备好之前, 系统调用会一直等待. 所有的套接字, 默认都是阻塞方式
在这里插入图片描述

1.2 非阻塞IO

非阻塞IO: 如果内核还未将数据准备好, 系统调用仍然会直接返回, 并且返回EWOULDBLOCK错误码.
非阻塞IO往往需要程序员循环的方式反复尝试读写文件描述符, 这个过程称为轮询. 这对CPU来说是较大的浪费, 一般只有特定场景下才使用
在这里插入图片描述
对比阻塞IO就是等的方式不同

1.3 信号驱动IO

信号驱动IO: 内核将数据准备好的时候, 使用SIGIO信号通知应用程序进行IO操作.
在这里插入图片描述
对于这种IO,就是需要进行信号捕捉

1.4 多路复用/多路转接IO

IO多路转接: 虽然从流程图上看起来和阻塞IO类似. 实际上最核心在于IO多路转接能够同时等待多个文件描述符的就绪状态.
在这里插入图片描述
它的效率是最高的,因为它能同时等待多个IO

1.5 异步IO

异步IO: 由内核在数据拷贝完成时, 通知应用程序(而信号驱动是告诉应用程序何时可以开始拷贝数据).
它并没有参与等或者拷贝的过程,它是由系统完成的,它只需要完成处理数据
在这里插入图片描述

1.6 小结

任何IO过程中, 都包含两个步骤. 第一是等待, 第二是拷贝. 而且在实际的应用场景中, 等待消耗的时间往往都远远高于拷贝的时间. 让IO更高效, 最核心的办法就是让等待的时间尽量少.

2.高级IO重要概念

同步通信 vs 异步通信(synchronous communication/ asynchronous communication)

同步和异步关注的是消息通信机制.
所谓同步,就是在发出一个调用时,在没有得到结果之前,该调用就不返回. 但是一旦调用返回,就得到返回值了; 换句话说,就是由调用者主动等待这个调用的结果;
异步则是相反,调用在发出之后,这个调用就直接返回了,所以没有返回结果; 换句话说,当一个异步过程调用发出后,调用者不会立刻得到结果; 而是在调用发出后,被调用者通过状态、通知来通知调用者,或通过回调函数处理这个调用.
另外, 在多进程多线程的时候, 也提到同步和互斥. 这里的同步通信和进程之间的同步是完全不想干的概念.
进程/线程同步也是进程/线程之间直接的制约关系
是为完成某种任务而建立的两个或多个线程,这个线程需要在某些位置上协调他们的工作次序而等待、传递信息所产生的制约关系. 尤其是在访问临界资源的时候.
看到 “同步” 这个词, 一定要先搞清楚大背景是什么. 这个同步, 是同步通信异步通信的同步, 还是同步与互斥的同步.

阻塞 vs 非阻塞

阻塞和非阻塞关注的是程序在等待调用结果(消息,返回值)时的状态.
阻塞调用是指调用结果返回之前,当前线程会被挂起. 调用线程只有在得到结果之后才会返回.
非阻塞调用指在不能立刻得到结果之前,该调用不会阻塞当前线程

3.非阻塞IO

一个文件描述符,默认都是阻塞IO的

函数fcntl

在这里插入图片描述

传入的cmd的值不同, 后面追加的参数也不相同.
fcntl函数有5种功能:
复制一个现有的描述符(cmd=F_DUPFD).
获得/设置文件描述符标记(cmd=F_GETFD或F_SETFD).
获得/设置文件状态标记(cmd=F_GETFL或F_SETFL).
获得/设置异步I/O所有权(cmd=F_GETOWN或F_SETOWN).
获得/设置记录锁(cmd=F_GETLK,F_SETLK或F_SETLKW).
我们此处只是用第三种功能, 获取/设置文件状态标记, 就可以将一个文件描述符设置为非阻塞

3.1 实现函数NoBlock

void SetNoBlock(int fd)
{int fl = fcntl(fd, F_GETFL);if (fl < 0){cerr << "error string:" << strerror(errno) << endl;}fcntl(fd, F_SETFL, fl | O_NONBLOCK);
}

使用F_GETFL将当前的文件描述符的属性取出来(这是一个位图).
然后再使用F_SETFL将文件描述符设置回去. 设置回去的同时, 加上一个O_NONBLOCK参数

3.2 轮询方式读取标准输入

#include <iostream>
#include <unistd.h>
#include <fcntl.h>
#include <vector>
#include <string>
#include <cstring>
#include <functional>
using namespace std;
using func_t=function<void(void)>;
vector<func_t> task;
void PrintLog(void)
{cout<<"这是一个打印日志的例程"<<endl;
}void OperateMySQL(void)
{cout<<"这是一个操作数据库的例程"<<endl;
}void CheckNet(void)
{cout<<"这是一个检查网络的例程"<<endl;
}void LoadTask(void)
{task.push_back(PrintLog);task.push_back(OperateMySQL);task.push_back(CheckNet);
}void HandleTask()
{for(const auto& e:task){e();}
}void SetNoBlock(int fd)
{int fl = fcntl(fd, F_GETFL);if (fl < 0){cerr << "error string:" << strerror(errno) << endl;}fcntl(fd, F_SETFL, fl | O_NONBLOCK);
}int main()
{SetNoBlock(0);char buff[1024];LoadTask();while (1){cout << ">>>";fflush(stdout);//read三种状态:1.成功 2.结束 3.出错(一旦底层没有数据就绪,以出错的形式返回,但是不算真正的出错)ssize_t n = read(0, buff, sizeof(buff) - 1);if (n > 0){buff[n - 1] = '\0';cout << "echo# " << buff << endl;}else if (n == 0){cout << "end file" << endl;break;}else{if (errno == EAGAIN || errno == EWOULDBLOCK){// 底层数据没有准备好,希望你下次继续检测cout << "data wouldn't ready" << endl;HandleTask();//轮询的方式读取,先去完成别的任务,待会再回来检测sleep(1);continue;}else if (errno == EINTR){// 这次IO被信号中断,也需要被重新获取continue;}else{cerr << "read error,error string" << strerror(errno) << endl;break;}}}return 0;
}

在这里插入图片描述
其中当read读取时因为fd是设置为非阻塞的,所以说read所返回的errno是EWOULDBLOCK,表明读取时数据还没准备好,还处于阻塞状态
在这里插入图片描述

4.I/O多路转接之select

系统提供select函数来实现多路复用输入/输出模型.
select系统调用是用来让我们的程序监视多个文件描述符的状态变化的;
程序会停在select这里等待,直到被监视的文件描述符有一个或多个发生了状态改变;
在这里插入图片描述

参数解释:
参数nfds是需要监视的最大的文件描述符值+1;
rdset,wrset,exset分别对应于需要检测的可读文件描述符的集合,可写文件描述符的集合及异常文件描述符的集合;
参数timeout为结构timeval,用来设置select()的等待时间;
后四个是输入输出型参数
我们以readfds来举例:当它是输入参数时,表示用户告诉内核哪些fd读事件需要内核关心;当它是输出参数时,表示内核要告诉用户,哪些fd读事件已经就绪.他们都是fd_set类型,有固定大小,所以说比特位数一定有上限。select所能管理的fd一定有上限.用位图结构表示多个fd,来进行用户和内核之间信息的互相传递
在这里插入图片描述
其实这个结构就是一个整数数组, 更严格的说, 是一个 “位图”. 使用位图中对应的位来表示要监视的文件描述符.
提供了一组操作fd_set的接口, 来比较方便的操作位图.

void FD_CLR(int fd, fd_set *set); // 用来清除描述词组set中相关fd 的位int FD_ISSET(int fd, fd_set *set); // 用来测试描述词组set中相关fd 的位是否为真void FD_SET(int fd, fd_set *set); // 用来设置描述词组set中相关fd的位void FD_ZERO(fd_set *set); // 用来清除描述词组set的全部位

参数timeout取值:
在这里插入图片描述
①NULL:阻塞等待
②{0,0}:非阻塞等待
③{n,m}:例{5,0},5秒以内阻塞等待,否则timeout一次,返回的时候表示剩余时间
函数返回值:
执行成功则返回文件描述词状态已改变的个数
如果返回0代表在描述词状态改变前已超过timeout时间,没有返回
当有错误发生时则返回-1,错误原因存于errno,此时参数readfds,writefds, exceptfds和timeout的
值变成不可预测。

4.1 理解select执行过程

理解select模型的关键在于理解fd_set,为说明方便,取fd_set长度为1字节,fd_set中的每一bit可以对应一个文件描述符fd。则1字节长的fd_set最大可以对应8个fd.
(1)执行fd_set set; FD_ZERO(&set);则set用位表示是0000,0000。
(2)若fd=5,执行FD_SET(fd,&set)后set变为0001,0000(第5位置为1)
(3)若再加入fd=2,fd=1,则set变为0001,0011
(4)执行select(6,&set,0,0,0)阻塞等待
(5)若fd=1,fd=2上都发生可读事件,则select返回,此时set变为0000,0011。注意:没有事件发生的fd=5被清空

4.2 select的特点

可监控的文件描述符个数取决与sizeof(fd_set)的值. 我这边服务器上sizeof(fd_set)=128,每bit表示一个文件描述符,则我服务器上支持的最大文件描述符是128*8=1024.
将fd加入select监控集的同时,还要再使用一个数据结构array保存放到select监控集中的fd.
一是用于再select返回后,array作为源数据和fd_set进行FD_ISSET判断.
二是select返回后会把以前加入的但并无事件发生的fd清空,则每次开始select前都要重新从array取得
fd逐一加入(FD_ZERO最先),扫描array的同时取得fd最大值maxfd,用于select的第一个参数。
备注: fd_set的大小可以调整,可能涉及到重新编译内核.

4.3 select缺点

每次调用select, 都需要手动设置fd集合, 从接口使用角度来说也非常不便.
每次调用select,都需要把fd集合从用户态拷贝到内核态,这个开销在fd很多时会很大
同时每次调用select都需要在内核遍历传递进来的所有fd,这个开销在fd很多时也很大
select支持的文件描述符数量太小

对于进程而言可以打开100001个文件,因此对于进程来说select支持的文件描述符过于小
在这里插入图片描述

4.4 实现

Select实现标准输出
Select实现标准输入输出的大致轮廓

5.I/O多路转接之poll

5.1 poll函数

在这里插入图片描述
在这里插入图片描述

参数说明:
fds是一个poll函数监听的结构列表. 每一个元素中, 包含了三部分内容: 文件描述符, 监听的事件集合, 返回的事件集合.可以当做一个“数组”来看
nfds表示fds数组的长度.
timeout表示poll函数的超时时间, 单位是毫秒(ms),<0是阻塞,==0是非阻塞,>0是等待多少毫秒后返回
events和revents的取值:
在这里插入图片描述
返回结果:
返回值小于0, 表示出错;
返回值等于0, 表示poll函数等待超时;
返回值大于0, 表示poll由于监听的(个数)文件描述符就绪而返回.

5.2 poll的优点

不同与select使用三个位图来表示三个fdset的方式,poll使用一个pollfd的指针实现.
pollfd结构包含了要监视的event和发生的event,不再使用select“参数-值”传递的方式. 接口使用比
select更方便.
poll将输入参数和输出参数进行了分离,不用调用poll重新设置了
poll并没有最大数量限制 (但是数量过大后性能也是会下降).

5.3 poll的缺点

poll中监听的文件描述符数目增多时
和select函数一样,poll返回后,需要轮询pollfd来获取就绪的描述符.
每次调用poll都需要把大量的pollfd结构从用户态拷贝到内核中.
同时连接的大量客户端在一时刻可能只有很少的处于就绪状态, 因此随着监视的描述符数量的增长, 其效率也会线性下降.

5.4 实现

Poll实现标准输出

6.I/O多路转接之epoll

6.1 epoll的相关系统调用

epoll 有3个相关的系统调用
在这里插入图片描述

创建一个epoll的句柄.
自从linux2.6.8之后,size参数是被忽略的(>0).
用完之后, 必须调用close()关闭.

在这里插入图片描述

epoll的事件注册函数.
它不同于select()是在监听事件时告诉内核要监听什么类型的事件, 而是在这里先注册要监听的事件类型.
第一个参数是epoll_create()的返回值(epoll的句柄).
第二个参数表示动作,用三个宏来表示.
第三个参数是需要监听的fd.
第四个参数是告诉内核需要监听什么事.
第二个参数的取值:
EPOLL_CTL_ADD :注册新的fd到epfd中;
EPOLL_CTL_MOD :修改已经注册的fd的监听事件;
EPOLL_CTL_DEL :从epfd中删除一个fd;

在这里插入图片描述
在这里插入图片描述

events可以是以下几个宏的集合:
EPOLLIN : 表示对应的文件描述符可以读 (包括对端SOCKET正常关闭);
EPOLLOUT : 表示对应的文件描述符可以写;

EPOLLPRI : 表示对应的文件描述符有紧急的数据可读 (这里应该表示有带外数据到来);
EPOLLERR : 表示对应的文件描述符发生错误;
EPOLLHUP : 表示对应的文件描述符被挂断;
EPOLLET : 将EPOLL设为边缘触发(Edge Triggered)模式, 这是相对于水平触发(Level Triggered)来说的.
EPOLLONESHOT:只监听一次事件, 当监听完这次事件之后, 如果还需要继续监听这个socket的话,需要再次把这个socket加入到EPOLL队列里

在这里插入图片描述

收集在epoll监控的事件中已经发生的事件.
参数events是分配好的epoll_event结构体数组.
epoll将会把发生的事件赋值到events数组中 (events不可以是空指针,内核只负责把数据复制到这个events数组中,不会去帮助我们在用户态中分配内存).
maxevents告之内核这个events有多大,这个 maxevents的值不能大于创建epoll_create()时的size. 参数timeout是超时时间 (毫秒,0会立即返回,-1是永久阻塞).
如果函数调用成功,返回对应I/O上已准备好的文件描述符数目,如返回0表示已超时, 返回小于0表示函数失败

总的来说epoll_ctl是为了达成用户告诉内核所需要关心的哪个文件描述符上的哪个事件。而epoll_wait是内核要告诉用户关心的哪些文件描述符的哪些事件已经就绪了

6.2 epoll工作原理

首先我们要先知道一下操作系统是怎么知道网卡上面有数据了?这其实和之前信号部分的键盘输入的问题类似,当网卡拿到数据后,会触发对应CPU的引脚的中断号,CPU把它交给CPU中的寄存器,就是对其进行充放电(二进制),而对应的中断号是中断向量表的下标,中断向量表是一个函数指针数组,所以说软件层能够读到寄存器的内容,可以调用对应的函数来把数据从外设拷贝到内存
在这里插入图片描述
对于我们的epoll_create的返回值是一个文件描述符是为了当调用epoll_ctl和epoll_wait时能够找到并构建对应的红黑树和在就绪队列里取数据。
我们的红黑树和就绪队列是我们的OS维护的,整体一个大的模型称之为epoll模型。因此对于epoll_wait来说检查数据有没有就绪(检查就绪队列是否为空)的时间复杂度就是O(1)。
我们的strcut file中会有对应的回调机制,通过对应的回调函数将红黑树中的结点添加到就绪队列中国。当我们的操作系统处理完所有的数据后,会先检查对应的struct file中对应的函数指针是否为NULL,然后调用其函数。只有当我们使用epoll时这个函数指针会有对应的地址。

6.3 epoll的优点(和 select 的缺点对应)

接口使用方便: 虽然拆分成了三个函数, 但是反而使用起来更方便高效. 不需要每次循环都设置关注的文件描述符, 也做到了输入输出参数分离开
数据拷贝轻量: 只在合适的时候调用 EPOLL_CTL_ADD 将文件描述符结构拷贝到内核中, 这个操作并不频繁(而select/poll都是每次循环都要进行拷贝)
内核中的红黑树也能提高查找的效率和去重
事件回调机制: 避免使用遍历, 而是使用回调函数的方式, 将就绪的文件描述符结构加入到就绪队列中, epoll_wait 返回直接访问就绪队列就知道哪些文件描述符就绪. 这个操作时间复杂度O(1). 即使文件描述符数目很多, 效率也不会受到影响.
没有数量限制: 文件描述符数目无上限

6.4 epoll工作方式

epoll有2种工作方式:水平触发(LT)和边缘触发(ET)

假如有这样一个例子:
我们已经把一个tcp socket添加到epoll描述符
这个时候socket的另一端被写入了2KB的数据
调用epoll_wait,并且它会返回. 说明它已经准备好读取操作
然后调用read, 只读取了1KB的数据
继续调用epoll_wait…

水平触发Level Triggered 工作模式
epoll默认状态下就是LT工作模式.
当epoll检测到socket上事件就绪的时候, 可以不立刻进行处理. 或者只处理一部分.
如上面的例子, 由于只读了1K数据, 缓冲区中还剩1K数据, 在第二次调用 epoll_wait 时, epoll_wait仍然会立刻返回并通知socket读事件就绪.
直到缓冲区上所有的数据都被处理完, epoll_wait 才不会立刻返回.
支持阻塞读写和非阻塞读写

边缘触发Edge Triggered工作模式
如果我们在第1步将socket添加到epoll描述符的时候使用了EPOLLET标志, epoll进入ET工作模式.
当epoll检测到socket上事件就绪时, 必须立刻处理.
如上面的例子, 虽然只读了1K的数据, 缓冲区还剩1K的数据, 在第二次调用 epoll_wait 的时候, epoll_wait 不会再返回了.
也就是说, ET模式下, 文件描述符上的事件就绪后, 只有一次处理机会. 数据从有无到有会有通知,从有到多,产生变化,会有第二次通知
ET的性能比LT性能更高( epoll_wait 返回的次数少了很多). Nginx默认采用ET模式使用epoll.
只支持非阻塞的读写
select和poll其实也是工作在LT模式下. epoll既可以支持LT, 也可以支持ET.

6.5 对比LT和ET

LT是 epoll 的默认行为. 使用 ET 能够减少 epoll 触发的次数,相等于减少系统调用. 但是代价就是强逼着程序猿一次响应就绪过程中就把所有的数据都处理完.相当于一个文件描述符就绪之后, 不会反复被提示就绪, 看起来就比 LT 更高效一些. 但是在 LT 情况下如果也能做到每次就绪的文件描述符都立刻处理, 不让这个就绪被重复提示的话, 其实性能也是一样的.另一方面, ET 的代码复杂程度更高了。他们二者的通知效率其实是ET>=LT的,因为LT也可能会遇到上层立马把数据读取的情况,并且ET可以做到百分之百的减少epoll的触发,而LT万一代码出现问题,效率就不一定有ET高了,其实高效的本质也是让TCP的底层更新出更大的接收窗口,从而在较大概率上能让对方的滑动窗口更大,提高发送效率。
LT更适合用于需要边接收边处理的场景,而ET是高效的IO

6.6 实现

EpollServerV1
EpollServerV2
EpollServerV3
上面的就是Reactor模式,基于多路转接的包含事件派发器,连接管理器等半同步半异步的IO服务器,Reactor翻译过来是反应堆的意思,可以理解为有一个connection就绪了,就会去处理,调用回调,底层读写。

🌸🌸高级IO的知识大概就讲到这里啦,博主后续会继续更新更多Linux的相关知识,干货满满,如果觉得博主写的还不错的话,希望各位小伙伴不要吝啬手中的三连哦!你们的支持是博主坚持创作的动力!💪💪

相关文章:

Linux高级IO

高级IO 1.五种IO模型1.1 阻塞IO1.2 非阻塞IO1.3 信号驱动IO1.4 多路复用/多路转接IO1.5 异步IO1.6 小结 2.高级IO重要概念3.非阻塞IO3.1 实现函数NoBlock3.2 轮询方式读取标准输入 4.I/O多路转接之select4.1 理解select执行过程4.2 select的特点4.3 select缺点4.4 实现 5.I/O多…...

go-admin-ui开源后台管理系统华为云部署

1.华为云开通8000与9527端口 2.编译 编译成功 3.发布到远程服务器 4.登陆华为云终端 5.安装Nginx 6.查看服务启动状态 7.添加网站 添加与修改配置www-data 改为 www 自定义日志输出格式 添加网站配置文件go_admin_ui.conf 添加如下内容: location 下的root指向网站文件夹 修…...

点云入门知识

点云的处理任务 场景语义分割 物体的三维表达方法&#xff08;3D representations&#xff09;&#xff1a; 点云&#xff1a;是由物体表面上许多点数据来表征这个物体。最接近原始传感器数据&#xff0c;且具有丰富的几何信息。 Mesh&#xff1a;用三角形面片和正方形面片拼…...

HTML静态网页成品作业(HTML+CSS+JS)——家乡莆田介绍网页(5个页面)

&#x1f389;不定期分享源码&#xff0c;关注不丢失哦 文章目录 一、作品介绍二、作品演示三、代码目录四、网站代码HTML部分代码 五、源码获取 一、作品介绍 &#x1f3f7;️本套采用HTMLCSS&#xff0c;使用Javacsript代码实现图片轮播&#xff0c;共有5个页面。 二、作品…...

#### grpc比http性能高的原因 ####

grpc比http性能高的原因 二进制消息格式&#xff1a;gRPC使用Protobuf&#xff08;一种有效的二进制消息格式&#xff09;进行序列化&#xff0c;这种格式在服务器和客户端上的序列化速度非常快&#xff0c;且序列化后的消息体积小&#xff0c;适合带宽有限的场景。 HTTP/2协…...

微软Edge浏览器搜索引擎切换全攻略

微软Edge浏览器作为Windows 10的默认浏览器&#xff0c;提供了丰富的功能和良好的用户体验。其中&#xff0c;搜索引擎的切换功能允许用户根据个人喜好和需求&#xff0c;快速更换搜索引擎&#xff0c;从而获得更加个性化的搜索服务。本文将详细介绍如何在Edge浏览器中进行搜索…...

<Linux> 实现命名管道多进程任务派发

实现命名管道多进程任务派发 common文件 #ifndef _COMMON_H_ #define _COMMON_H_#pragma once #include <iostream> #include <unistd.h> #include <string> #include <sys/types.h> #include <sys/stat.h> #include <wait.h> #include &…...

BigInteger 和 BigDecimal(java)

文章目录 BigInteger(大整数&#xff09;常用构造方法常用方法 BigDecimal(大浮点数&#xff09;常用构造方法常用方法 DecimalFormat(数字格式化) BigInteger(大整数&#xff09; java.math.BigInteger。 父类&#xff1a;Number 常用构造方法 构造方法&#xff1a;BigIntege…...

Linux 进程间通讯

Linux IPC 方式 在Linux系统中&#xff0c;进程间通信&#xff08;IPC&#xff09;是多个运行中的程序或进程之间交换数据和信息的关键机制。Linux提供了多种IPC机制&#xff0c;每种机制都有其特定的用途和优势。以下是Linux上主要的IPC通信方式&#xff1a; 管道&#xff08…...

数据分析三剑客-Matplotlib

数据分析三剑客 数据分析三剑客通常指的是在Python数据分析领域中&#xff0c;三个非常重要的工具和库&#xff1a;Pandas、NumPy和Matplotlib。Pandas主要负责数据处理和分析&#xff0c;NumPy专注于数值计算和数学运算&#xff0c;而Matplotlib则负责数据可视化。这三个库相…...

FastAPI-Body、Field

参考&#xff1a;模式的额外信息 - 例子 - FastAPI 在FastAPI中&#xff0c;Body和Field是两个常用的注解&#xff0c;它们用于定义请求体中的数据或路径参数、查询参数等的处理方式。这两个注解都来自于Pydantic库&#xff0c;用于数据验证和解析&#xff0c;但它们的应用场景…...

软件设计师笔记-操作系统知识(二)

线程 以下是关于线程的一些关键点&#xff1a; 线程是进程中的一个实体&#xff1a;进程是操作系统分配资源&#xff08;如内存空间、文件句柄等&#xff09;的基本单位&#xff0c;而线程是进程中的一个执行单元。多个线程可以共享同一个进程的地址空间和其他资源。线程是CP…...

鸿蒙UI开发快速入门 —— part12: 渲染控制

如果你对鸿蒙开发感兴趣&#xff0c;加入Harmony自习室吧~&#x1f447;&#x1f3fb;&#x1f447;&#x1f3fb;&#x1f447;&#x1f3fb;&#x1f447;&#x1f3fb; 扫描下面的二维码关注公众号。 1、前言 在声明式描述语句中开发者除了使用系统组件外&#xff0c;还可…...

添加用户页面(Flask+前端+MySQL整合)

首先导入Flask库和pymysql库。Flask用于创建Web应用程序&#xff0c;pymysql用于连接和操作MySQL数据库。 from flask import Flask, render_template, request import pymysql创建一个Flask应用实例。__name__参数告诉Flask使用当前模块作为应用的名称。 app Flask(__name_…...

素数筛(算法篇)

算法之素数筛 素数筛 引言&#xff1a; 素数(质数)&#xff1a;除了1和自己本身之外&#xff0c;没有任何因子的数叫做素数(质数) 朴素筛法(优化版) 概念&#xff1a; 朴素筛法&#xff1a;是直接暴力枚举2到当前判断的数x(不包括)&#xff0c;然后看在这范围内是否存在因…...

迁移Microsoft Edge

如何将Microsoft Edge迁移到d盘&#xff1f;对于Microsoft Edge想必大部分人都不陌生&#xff0c;它是Windows操作系统的默认浏览器&#xff0c;存储用户的个人数据、缓存和设置等信息。有些时候&#xff0c;我们需要对Microsoft Edge中的数据进行数据迁移&#xff0c;以释放c盘…...

Maven高级理解属性

属性 在这一章节内容中&#xff0c;我们将学习两个内容&#xff0c;分别是 属性版本管理 属性中会继续解决分模块开发项目存在的问题&#xff0c;版本管理主要是认识下当前主流的版本定义方式。 4.1 属性 4.1.1 问题分析 讲解内容之前&#xff0c;我们还是先来分析问题: …...

Trilium Notes浏览器插件保存网页内容到docker私有化部署

利用Trilium浏览器插件可以很方便的把网页内容保存到Trilium&#xff0c;需要先在docker部署好trilium&#xff0c;还没有部署的可以先看这篇文章&#xff1a;trilium笔记私有化部署-www.88531.cn资享网 1.下载Trilium浏览器插件&#xff1a;https://www.npspro.cn/33462.html…...

C++ 统计二进制串中0出现的个数

描述 一个32位有符号整数&#xff0c;使用二进制来表示&#xff0c;现在要统计一下二进制串中0的个数。 示例1 输入&#xff1a; 11 返回值&#xff1a; 29 说明&#xff1a; 二进制00000000000000000000000000001011中有29位0 class Solution { public:/*** 代码中的…...

note-网络是怎样连接的6 请求到达服务器,响应返回浏览器

助记提要 服务器程序的结构套接字的指代方式MAC模块的接收过程IP模块的接收过程TCP模块处理连接包TCP模块处理数据包TCP模块的断开操作URI转换为实际文件路径URI调用程序Web服务器访问控制响应内容的类型 6章 请求到达服务器&#xff0c;响应返回浏览器 1 服务器概览 在数据…...

存储过程与函数:封装数据库逻辑的艺术(七)

引言 在上一章《事务处理》中&#xff0c;我们深入探讨了事务的ACID特性以及如何通过事务控制语句和隔离级别来确保数据的一致性和完整性。本章&#xff0c;我们将把焦点转向存储过程与函数&#xff0c;这是数据库系统中用于封装复杂业务逻辑和增强代码复用性的强大工具。通过…...

【复旦邱锡鹏教授《神经网络与深度学习公开课》笔记】卷积

卷积经常用在信号处理中&#xff0c;用于计算信号的延迟累积。假设一个信号发射器每个时刻 t t t产生一个信号 x t x_t xt​&#xff0c;其信息的衰减率为 w k w_k wk​&#xff0c;即在 k − 1 k-1 k−1个时间步长后&#xff0c;信息为原来的 w k w_k wk​倍&#xff0c;时刻 …...

Trie字符串统计

Trie字符串统计 维护一个字符串集合&#xff0c;支持两种操作&#xff1a; I x 向集合中插入一个字符串 x&#xff1b;Q x 询问一个字符串在集合中出现了多少次。 共有 N个操作&#xff0c;所有输入的字符串总长度不超过 105&#xff0c;字符串仅包含小写英文字母。 输入格式…...

Kali Linux源

中科大 deb http://mirrors.ustc.edu.cn/kali kali-rolling main non-free contrib deb-src http://mirrors.ustc.edu.cn/kali kali-rolling main non-free contrib阿里云 deb http://mirrors.aliyun.com/kali kali-rolling main non-free contrib deb-src http://mirrors.…...

【RT摩拳擦掌】基于RT106L/S语音识别的百度云控制系统

【RT摩拳擦掌】基于RT106L/S语音识别的百度云控制系统 一 文档简介二 平台构建2.1 使用平台2.2 百度智能云2.2.1 物联网核心套件2.2.2 在线语音合成 2.3 playback语音数据准备与烧录2.4 开机语音准备与添加2.5 唤醒词识别词命令准备与添加 三 代码准备3.1 sln-local/2-iot 代码…...

国标GB28181视频汇聚平台EasyCVR设备展示数量和显示条数不符的原因排查与解决

国标GB28181/GA/T1400协议/安防综合管理系统EasyCVR视频汇聚平台能在复杂的网络环境中&#xff0c;将前端设备统一集中接入与汇聚管理。智慧安防/视频存储/视频监控/视频汇聚EasyCVR平台可以提供实时远程视频监控、视频录像、录像回放与存储、告警、语音对讲、云台控制、平台级…...

FastAPI教程I

本文参考FastAPI教程https://fastapi.tiangolo.com/zh/tutorial 第一步 import uvicorn from fastapi import FastAPIapp FastAPI()app.get("/") async def root():return {"message": "Hello World"}if __name__ __main__:uvicorn.run(&quo…...

如何在 HTML 中实现响应式设计以适应不同设备的屏幕尺寸?

要在HTML中实现响应式设计以适应不同设备的屏幕尺寸&#xff0c;可以使用CSS媒体查询和流动布局。 以下是实现响应式设计的一些关键步骤&#xff1a; 使用CSS媒体查询&#xff1a;CSS媒体查询允许根据屏幕尺寸和设备特性应用不同的CSS样式。通过在CSS中使用media规则&#xf…...

【基础篇】第1章 Elasticsearch 引言

1.1 Elasticsearch简介 1.1.1 基本概念 Elasticsearch&#xff0c;一个开源的分布式搜索引擎&#xff0c;以其强大的搜索能力和实时数据分析能力&#xff0c;在大数据时代脱颖而出。它基于Apache Lucene库构建&#xff0c;旨在提供高效、可扩展且易于使用的全文检索解决方案。…...

在区块链技术广泛应用的情况下,C 语言如何在区块链的底层开发中发挥更有效的作用,提高性能和安全性?

C语言在区块链底层开发中发挥着重要的作用&#xff0c;可以提高性能和安全性。具体可以从以下几个方面进行优化&#xff1a; 性能优化&#xff1a;C语言是一种高效的编程语言&#xff0c;可以直接访问内存和硬件资源。在区块链底层开发中&#xff0c;使用C语言可以更好地利用底…...

量化投资 日周月报 2024-06-28

文章 深度学习在量化交易中的应用:在BigQuant量化交易平台的文章中,探讨了深度学习在量化交易中,特别是在因子挖掘方面的应用。文章提到,随着传统线性模型的潜力逐渐枯竭,非线性模型逐渐成为量化交易的主要探索方向。深度学习因其对非线性关系的拟合能力,在量化交易中展现…...

基于 Paimon 的袋鼠云实时湖仓入湖实战剖析

在当今数据驱动的时代&#xff0c;企业对数据的实施性能力提出了前所未有的高要求。为了应对这一挑战&#xff0c;构建高效、灵活且可扩展的实时湖仓成为数字化转型的关键。本文将深入探讨袋鼠云数栈如何通过三大核心实践——ChunJun 融合 Flink CDC、MySQL 一键入湖至 Paimon …...

IPython相关了解

一、什么是 IPython&#xff1f; 1.1 简单理解 IPython IPython 是一种增强的 Python 交互式解释器&#xff0c;它可以让你更方便地编写、调试和运行 Python 代码。你可以把它想象成一个比普通 Python 解释器更聪明、功能更丰富的工具&#xff0c;非常适合用来进行数据探索、…...

华为面试题及答案——机器学习(二)

21. 如何评价分类模型的优劣? (1)模型性能指标 准确率(Accuracy): 定义:正确分类的样本数与总样本数之比。适用:当各类样本的数量相对均衡时。精确率(Precision): 定义:预测为正类的样本中实际为正类的比例。适用:当关注假阳性错误的成本较高时(例如垃圾邮件检测…...

PlatformIO开发环境

PlatformIO是一个开源的生态系统&#xff0c;用于构建物联网应用&#xff0c;它支持多种微控制器&#xff08;MCU&#xff09;和硬件开发板&#xff0c;并且与各种IDE集成良好&#xff0c;如VSCode, Atom等&#xff0c;使得跨平台的固件开发变得更加简单和高效。 ### 平台介绍…...

In install.packages(“devtools“, verbose = TRUE) :

错误于curl::curl_download("https://r-lib.github.io/gert/libgit2-1.1.0.x86_64_legacy-linux.tar.gz", : Timeout was reached: [] Connection timed out after 10004 milliseconds 停止执行 Using PKG_CFLAGS Using PKG_LIBS-lgit2 ----------------------------…...

计算机网络 访问控制列表以及NAT

一、理论知识 1. 单臂路由 单臂路由是一种在路由器上配置多个子接口的方法&#xff0c;每个子接口代表不同的 VLAN&#xff0c;用于在一个物理接口上支持多 VLAN 通信。此方法使得不同 VLAN 之间可以通过路由器进行通信。 2. NAT (网络地址转换) NAT 是一种在私有网络和公共…...

使用Oracle IMP导入数据

使用Oracle IMP导入数据 大家好&#xff0c;我是免费搭建查券返利机器人省钱赚佣金就用微赚淘客系统3.0的小编&#xff0c;也是冬天不穿秋裤&#xff0c;天冷也要风度的程序猿&#xff01;今天我们来聊一聊如何使用Oracle的IMP工具来导入数据。 一、什么是Oracle IMP Oracle…...

C++ 100 之 容器插入和删除

vector插入和删除操作 insert(const_iterator pos, int count,ele);//迭代器指向位置pos插入count个元素ele. push_back(ele); //尾部插入元素ele pop_back();//删除最后一个元素 erase(const_iterator start, const_iterator end);//删除迭代器从start到end之间的元素 erase(c…...

提升 Selenium 测试稳定性的秘诀:深入理解等待 API 的使用

目录 为什么需要等待Selenium 等待 API 简介隐式等待显式等待Fluent Wait等待策略的选择示例代码总结 正文 1. 为什么需要等待 在 Web 自动化测试中&#xff0c;等待是一个关键因素。网络应用通常是动态的&#xff0c;页面加载时间、元素的显示时间都可能不同步。直接操作这…...

Python-算法编程100例-滑动窗口(入门级)

题目1&#xff1a;最大连续1的个数&#xff08;简单&#xff09; 给定一个二进制数组 nums &#xff0c; 计算其中最大连续 1 的个数。 解答&#xff1a;前缀和双指针 # 给定一个二进制数组 nums &#xff0c; 计算其中最大连续 1 的个数。 from typing import Listclass So…...

ffmpeg使用mjpeg把yuvj420p编码为jpg图像

version #define LIBAVUTIL_VERSION_MAJOR 58 #define LIBAVUTIL_VERSION_MINOR 12 #define LIBAVUTIL_VERSION_MICRO 100 node 不使用AVOutputFormat code void CFfmpegOps::EncodeYUVJ420pToMJPEG(const char* infile, const char* width_str, const char* height_s…...

龙迅#LT6911GXC支持HDMI2.1转MIPI/4PORT LVDS应用功能,分辨率高达8K30HZ/4K120HZ压缩格式。

1. 描述 该LT6911GXC是一款高性能HD-DVI2.1转MIPI或LVDS芯片&#xff0c;适用于VR/显示应用。 HDCP RX作为HDCP中继器的上游&#xff0c;可以与其他芯片的HDCP TX配合实现中继器功能。 对于 HD-DVI2.1 输入&#xff0c;LT6911GXC可以配置为 3/4 通道。 对于MIPI输出&#xff0c…...

.NET 6.0 Web API项目中实现基于Token的身份验证

本文以一个完整的示例&#xff0c;展示如何在.NET 6.0 Web API项目中实现基于Token的身份验证。这个例子包括了如何创建和验证JWT Token&#xff0c;以及如何在控制器中使用这些Token。 步骤 1: 创建Web API项目 首先&#xff0c;用Visual Studio 2022创建一个基于.NET6.0的 …...

Java常用对象的快速初始化

在Java中&#xff0c;有多种方式来快速初始化各种常用对象&#xff0c;如字符串数组&#xff08;String[]&#xff09;&#xff0c;集合列表&#xff08;List&#xff09;&#xff0c;映射表&#xff08;Map&#xff09;&#xff0c;以及集合&#xff08;Set&#xff09;。不同…...

逻辑回归模型模拟实现:从零开始

引言 逻辑回归是一种用于二分类问题的机器学习算法。尽管它的名字中有“回归”&#xff0c;但它实际上是用于分类的。在本文中&#xff0c;我们将通过模拟数据来演示逻辑回归模型的实现。 逻辑回归简介 逻辑回归通过使用逻辑函数&#xff08;通常是Sigmoid函数&#xff09;将…...

Docker基本使用和认识

目录 基本使用 镜像仓库 镜像操作 Docker 如何实现镜像 1) namespace 2) cgroup 3) LXC Docker常见的网络类型 bridge网络如何实现 基本使用 镜像仓库 镜像仓库登录 1)docker login 后面不指定IP地址&#xff0c;则默认登录到 docker hub 上 退出 2)docker logo…...

Halcon 文本文件操作,形态学

一文件的读写 *******************************************************向文本文件写入字符串内容*************************************************************read_image (Image, fabrik)threshold (Image, Region, 0, 120)area_center (Region, Area, Row, Column)open_…...

【鸿蒙】稍微理解一下Stage模型

鸿蒙的Stage模型是HarmonyOS多端统一的应用开发框架中的一个核心概念&#xff0c;用于描述应用的界面层次结构和组件之间的关系。下面将详细解析Stage模型的主要组成部分和特点&#xff1a; 模型组成&#xff1a; UIAbility组件&#xff1a;这是应用中负责绘制用户界面的组件&a…...

毕业答辩制作PPT【攻略】

毕业答辩制作PPT【攻略】 前言版权毕业答辩制作PPT【攻略】一、WPS AI 15天免费会员二、AI文档生成PPT三、修改完善PPT 最后 前言 2024-06-14 23:43:05 以下内容源自《【攻略】》 仅供学习交流使用 版权 禁止其他平台发布时删除以下此话 本文首次发布于CSDN平台 作者是CSDN…...

微信小程序文件结构示例

微信小程序文件结构示例 miniprogram │ ├── app.js // 小程序逻辑 ├── app.json // 全局配置 ├── app.wxss // 全局样式 │ ├── pages // 页面文件夹 │ ├── index // 首页 │ │ ├── index.js // 页面逻辑 │ │ ├── index.json // 页面配置 │ │ ├─…...

Pytorch实战(一):LeNet神经网络

文章目录 一、模型实现1.1数据集的下载1.2加载数据集1.3模型训练1.4模型预测 LeNet神经网络是第一个卷积神经网络&#xff08;CNN&#xff09;&#xff0c;首次采用了卷积层、池化层这两个全新的神经网络组件&#xff0c;接收灰度图像&#xff0c;并输出其中包含的手写数字&…...

有哪些好的 Stable Diffusion 提示词(Prompt)可以参考?

Docker 作图咒语生成器 docker-prompt-generator 是一个开源项目&#xff0c;可以利用模型反推出提示词&#xff0c;让你偷偷懒&#xff0c;无需琢磨怎么写prompt&#xff0c;只需要找一个差不多的模型反推一下&#xff0c;直接用就好了&#xff0c;支持支持 MidJourney、Stab…...

Python学习打卡:day16

day16 笔记来源于&#xff1a;黑马程序员python教程&#xff0c;8天python从入门到精通&#xff0c;学python看这套就够了 目录 day16116、SQL 基础和 DDLSQL的概述SQL语言的分类SQL的语法特征DDL — 库管理DDL — 表管理 117、SQL — DMLDML概述数据插入 INSERT数据删除 DEL…...

淘宝扭蛋机小程序开发,新玩法、新收益体验!

近几年&#xff0c;随着娱乐消费的火爆&#xff0c;潮玩市场得到了快速发展&#xff0c;从而带动了扭蛋机市场的发展&#xff0c;扭蛋机也逐渐风靡在消费市场中。对于年轻人消费者来说&#xff0c;愿意为扭蛋机的热门IP商品而买单。目前&#xff0c;价格低、颜值高、种类多样的…...

编译器的控制流图分析

1&#xff0c;建立感性认识 1.1 源码 hello.c int x 10; int y 11; int main(){int z 12;for (int i 0;i < 10;i){z * x * y;}if(z>7.0)z1.0f;elsez 2.0f;return 0; }1.2 编译 2005 sudo apt-get install -y graphviz-doc libgraphviz-dev graphviz2034 ../ex_…...

4JJ1动力+定制化冷厢翼放冷链版助你夏日创富遥遥领“鲜”

夏日高温,对于生鲜食材的运输来说是个巨大的挑战。如何确保物品新鲜及时的送达,成为摆在物流行业面前不得不思考的问题。冷链物流的重要性愈发凸显,而高效、可靠的冷藏车则成为了解决这一问题的关键。那么,面对市场上琳琅满目的冷藏车产品,如何选到一款既省心又高效赚钱的…...

2141.4km!星纪元ET全球上市,18.98万元起

5月9日,星纪元ET正式全球上市,共推出8个版型,分别为增程系列:Plus 18.98万元、Pro 20.58万元、Pro+22.58万元,以及纯电系列:Pro22.98万元、Pro四驱23.98万元、Pro城市智驾24.98万元、Max 27.98万元、Ultra 31.98万元。官方还同步公布置换礼、金融礼等多重上市权益豪礼,并将…...

深圳建设“超充之城”提速

五分钟的时间可以做什么?也许只是白领喝一杯咖啡的时间,但在深圳,能给新能源汽车续航200公里。在深圳的超充站,“一杯咖啡,满电出发”的标语十分醒目。深圳随处可见的超充标语近日,记者从深圳市发展改革委获悉,截至5月17日,深圳累计建成超充站378座。深圳“超充之城”建…...

【微机原理及接口技术】可编程计数器/定时器8253

【微机原理及接口技术】可编程计数器/定时器8253 文章目录 【微机原理及接口技术】可编程计数器/定时器8253前言一、8253的内部结构和引脚二、8253的工作方式三、8253的编程总结 前言 本篇文章就8253芯片展开&#xff0c;详细介绍8253的内部结构和引脚&#xff0c;8253的工作方…...

css卡片翻转 父元素翻转子元素不翻转效果

css卡片翻转 父元素翻转子元素不翻转效果 vue <div class"moduleBox"><div class"headTitle"><span class"headName">大额案例</span></div><div class"moduleItem"><span class"module…...

Python面试宝典:Python中与动态规划和排序算法相关的面试笔试题(1000加面试笔试题助你轻松捕获大厂Offer)

Python面试宝典:1000加python面试题助你轻松捕获大厂Offer【第二部分:Python高级特性:第十二章:高级数据结构和算法:第二节:Python中实现各类高级数据结构与算法三】 第十二章:高级数据结构和算法第二节:Python中实现各类高级数据结构与算法2.3、python中与动态规划和排…...