Linux——多路IO

IO多路复用

定义:单线程或单进程同时监测若IO干个文件描述符是否可以执行IO操作的能力

作用:
应用程序通常需要处理来自多条事件流中的事件,比如我现在用的电脑,需要同时处理键盘鼠标的输入、中断信号等等事件,再比如web服务器如nginx,需要同时处理来来自N个客户端的事件。

逻辑控制流在时间上的重叠叫做 并发

而CPU单核在同一时刻只能做一件事情,一种解决办法是对CPU进行时分复用(多个事件流将CPU切割成多个时间片,不同事件流的时间片交替进行)。在计算机系统中,我们用线程或者进程来表示一条执行流,通过不同的线程或进程在操作系统内部的调度,来做到对CPU处理的时分复用。这样多个事件流就可以并发进行,不需要一个等待另一个太久,在用户看起来他们似乎就是并行在做一样。

使用并发处理的成本:
线程/进程创建成本
CPU切换不同线程/进程成本 Context Switch
多线程的资源竞争

有没有一种可以在单线程/进程中处理多个事件流的方法呢?一种答案就是IO多路复用。

因此IO多路复用解决的本质问题是在用更少的资源完成更多的事。

IO模型

1、阻塞IO  
2、非阻塞IO  EAGAIN  忙等待 errno
3、信号驱动IO  SIGIO 用的相对少(了解)
4、并行模型 进程,线程
5, IO多路复用  select、poll、epoll

 



1、阻塞IO ===》最常用 默认设置

### 1. 阻塞IO

**定义**:
阻塞IO指的是需要内核IO操作彻底完成后才返回到用户空间执行用户程序的操作指令。在阻塞IO模型中,当用户进程发起一个IO请求(如读取文件或网络数据)时,进程会被阻塞,直到IO操作完成,内核将数据准备好并返回给用户进程。如果IO操作需要很长时间,那么用户进程将在这段时间内无法执行其他操作。

**特点**:
- 同步IO的一种形式。
- 用户进程在等待IO操作完成时处于阻塞状态,不能执行其他任务。
- 在Java中,默认创建的socket属于阻塞IO模型。


   IO:
   scanf()/printf() ====>默认的IO设备

   fgetc()/fputc()  ====》标准IO
   fgets()/fputs()  fp, stdin
   fread()/fwrite()
   
   read()/write()  ====》文件IO,pipe fifo

   recv()/send()   ====>tcp socket
   recfrom()/sendto() ===>udp socket

   scanf  fgetc  fgets fread read recv recvfrom  ==>阻塞等待

w

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <errno.h>
int main(int argc, char *argv[])
{int ret = mkfifo("myfifo",0666);    if(-1 == ret){//如果是管道文件已存在错误,让程序继续运行if(EEXIST== errno){}else {perror("mkfifo");exit(1);}}//open 会阻塞,等到另一端读段打开,解除阻塞int fd = open("myfifo",O_WRONLY);if(-1 == fd){perror("open");exit(1);}while(1){char buf[256]="hello,fifo,test";write(fd,buf,strlen(buf));sleep(3);}close(fd);return 0;
}

r

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <errno.h>int main(int argc, char *argv[])
{int ret = mkfifo("myfifo",0666);    if(-1 == ret){//如果是管道文件已存在错误,让程序继续运行if(EEXIST== errno){}else {perror("mkfifo");exit(1);}}int fd = open("myfifo",O_RDONLY);if(-1 == fd){perror("open");exit(1);}while(1){char buf[256]={0};read(fd,buf,sizeof(buf));printf("fifo %s\n",buf);bzero(buf,sizeof(buf));fgets(buf,sizeof(buf),stdin);printf("terminal:%s\n",buf);}close(fd);//remove("myfifo");return 0;
}

### 2. 非阻塞IO

**定义**:
非阻塞IO是程序在发送一个IO请求后无需等待其响应,期间可以执行其他任务,从而提高了程序运行的效率。如果IO操作不能立即完成,非阻塞IO会返回一个错误代码(如EWOULDBLOCK或EAGAIN),表示IO操作尚未完成。

**特点**:
- 用户进程发起IO请求后不会立即阻塞,而是可以立即返回继续执行其他任务。
- 如果IO操作尚未完成,会收到错误代码提示。

**EAGAIN**:
- EAGAIN是非阻塞IO中常见的错误代码之一,表示资源暂时不可用,需要稍后重试。
- 当用户进程在非阻塞模式下尝试读取或写入数据时,如果数据尚未准备好或缓冲区已满,就会收到EAGAIN错误。

**忙等待**:
- 忙等待通常与非阻塞IO结合使用,指的是在用户进程收到EAGAIN错误后,通过循环检查IO状态的方式等待IO操作完成。
- 这种方式会消耗CPU资源,因为进程需要不断检查IO状态,而不是被阻塞或进行其他有用的工作。



2.1 在程序开始阶段调整文件的打开方式为非阻塞:
===》open()===>fifo()的同步。
open("fifo",O_RDONLY|O_NONBLOCK);
====>read() 不再阻塞。

2.2 在程序执行阶段调整文件的执行方式为非阻塞:
===》fcntl() ===>动态调整文件的阻塞属性

#include <unistd.h>
#include <fcntl.h>
int fcntl(int fd, int cmd, ... /* arg */ );
功能:修改指定文件的属性信息。
参数:fd 要调整的文件描述符
  cmd 要调整的文件属性宏名称
  ... 可变长的属性值参数。
返回值:成功  不一定,看cmd
失败  -1;

eg:修改文件的非阻塞属性:
int flag ;
flag  = fcntl(fd,F_GETFL,0);  ///获取fd文件的默认属性到flag变量中。
flag  = flag | O_NONBLOCK;    ///将变量的值调整并添加非阻塞属性
fcntl(fd,F_SETFL,flag);       ///将新属性flag设置到fd对应的文件生效。

以上代码执行后的阻塞IO将变成非阻塞方式。

练习:编写fifo测试函数,完成fcntl控制的非阻塞方式读写。
  修改之前的tcp,udp程序用fcntl测试其非阻塞特性。

  如果是recv()/recvfrom()===》参数flags == MSG_DONTWAIT
  如果是read()   ====>fcntl()

w

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <errno.h>
int main(int argc, char *argv[])
{int ret = mkfifo("myfifo",0666);    if(-1 == ret){//如果是管道文件已存在错误,让程序继续运行if(EEXIST== errno){}else {perror("mkfifo");exit(1);}}//open 会阻塞,等到另一端读段打开,解除阻塞int fd = open("myfifo",O_WRONLY);if(-1 == fd){perror("open");exit(1);}while(1){char buf[256]="hello,fifo,test";write(fd,buf,strlen(buf));sleep(3);}close(fd);return 0;
}

r


#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <errno.h>int main(int argc, char *argv[])
{int ret = mkfifo("myfifo",0666);    if(-1 == ret){//如果是管道文件已存在错误,让程序继续运行if(EEXIST== errno){}else {perror("mkfifo");exit(1);}}int fd = open("myfifo",O_RDONLY);if(-1 == fd){perror("open");exit(1);}int flag = fcntl(fd,F_GETFL);flag = flag|O_NONBLOCK  ; fcntl(fd,F_SETFL,flag);flag = fcntl(0,F_GETFL);fcntl(0,F_SETFL,flag|O_NONBLOCK);while(1){char buf[256]={0};if(read(fd,buf,sizeof(buf))>0){printf("fifo %s\n",buf);}bzero(buf,sizeof(buf));if(fgets(buf,sizeof(buf),stdin)){printf("terminal:%s\n",buf);}}close(fd);//remove("myfifo");return 0;
}

3.信号驱动IO(SIGIO)

**定义**:
信号驱动IO是指进程预先告知内核,当某个socket或文件描述符有事件发生时,内核使用信号(如SIGIO)通知相关进程。这样,进程就可以在需要时处理IO事件,而无需轮询或阻塞等待。

**特点**:
- 异步IO的一种形式。
- 减少了CPU资源的浪费,因为进程可以在等待IO事件时执行其他任务。
- 需要操作系统支持信号机制。

3.信号驱动io 
    文件描述符需要追加 O_ASYNC 标志。
    设备有io事件可以执行时,内核发送SIGIO信号。
    
        1.追加标志
        int flag ;
        flag  = fcntl(fd,F_GETFL,0);
        fcntl(fd,F_SETFL,flag | O_ASYNC);    
        2.设置信号接收者
        fcntl(fd,F_SETOWN,getpid());//常用设置
        3.对信号进行捕获
        signal(SIGIO,myhandle);//

w


#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <errno.h>
int main(int argc, char *argv[])
{int ret = mkfifo("myfifo",0666);    if(-1 == ret){//如果是管道文件已存在错误,让程序继续运行if(EEXIST== errno){}else {perror("mkfifo");exit(1);}}//open 会阻塞,等到另一端读段打开,解除阻塞int fd = open("myfifo",O_WRONLY);if(-1 == fd){perror("open");exit(1);}while(1){char buf[256]="hello,fifo,test";write(fd,buf,strlen(buf));sleep(3);}close(fd);return 0;
}

r


#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <errno.h>
int main(int argc, char *argv[])
{int ret = mkfifo("myfifo",0666);    if(-1 == ret){//如果是管道文件已存在错误,让程序继续运行if(EEXIST== errno){}else {perror("mkfifo");exit(1);}}//open 会阻塞,等到另一端读段打开,解除阻塞int fd = open("myfifo",O_WRONLY);if(-1 == fd){perror("open");exit(1);}while(1){char buf[256]="hello,fifo,test";write(fd,buf,strlen(buf));sleep(3);}close(fd);return 0;
}

4.并行模型:进程与线程

**进程**:
- 是操作系统进行资源分配和调度的一个独立单元。
- 每个进程都有自己独立的内存空间和系统资源。
- 进程是程序在计算机上的一次执行活动,是系统运行程序的基本单位。

**线程**:
- 是进程的一个实体,是CPU调度和分派的基本单位。
- 它是比进程更小的独立运行的单位,线程之间共享进程中的资源。
- 一个进程中可以拥有多个线程,这些线程共享进程的内存空间和系统资源。

**并行**:
- 指两个或多个事件在同一时刻发生(同时发生)。
- 在并行计算中,多个任务或操作可以在同一时间内执行,通常需要多核处理器或多台计算机的支持。

5.  IO多路复用

**定义**:
IO多路复用是一种在单个线程中管理多个输入/输出通道的技术。它允许一个线程同时监听多个IO事件(如网络连接、文件读写等),并在有数据可读或可写时进行相应的处理,而不需要为每个通道创建一个独立的线程。

**特点**:
- 提高了IO操作的效率,减少了线程切换和上下文切换的开销。
- 常见的IO多路复用机制包括select、poll和epoll(Linux特有)。

**总结**:
以上是对阻塞IO、非阻塞IO(包括EAGAIN和忙等待)、IO多路复用、信号驱动IO(SIGIO)以及并行模型中进程和线程的详细解释。这些概念在操作系统、网络编程和并发编程中扮演着重要角色,理解和掌握它们对于开发高效、可靠的应用程序至关重要。


    #include <sys/select.h>

    #include <sys/time.h>
    #include <sys/types.h>
    #include <unistd.h>

    int select(int nfds, fd_set *readfds, fd_set *writefds,
                fd_set *exceptfds,
                struct timeval *timeout);
    功能:完成指定描述符集合中有效描述符的动态检测。
          该函数具有阻塞等待功能,在函数执行完毕后
          目标测试集合中将只保留最后有数据的描述符。

    参数:nfds 描述符的上限值,一般是链接后描述符的最大值+1;
          readfds 只读描述符集
          writefds 只写描述符集
          exceptfds 异常描述符集
          以上三个参数都是 fd_set * 的描述符集合类型
          timeout  检测超时 如果是NULL表示一直检测不超时 。

    返回值:超时 0
            失败  -1
            成功 >0


        为了配合select函数执行,有如下宏函数:
        void FD_CLR(int fd, fd_set *set);
        功能:将指定的set集合中编号为fd的描述符号删除。

        int  FD_ISSET(int fd, fd_set *set);
        功能:判断值为fd的描述符是否在set集合中,
              如果在则返回真,否则返回假。

        void FD_SET(int fd, fd_set *set);
        功能:将指定的fd描述符,添加到set集合中。

        void FD_ZERO(fd_set *set);
        功能:将指定的set集合中所有描述符删除。


        select poll epoll的区别

1. select
int select(int nfds, fd_set *readfds, fd_set *writefds, fd_set *exceptfds, struct timeval *timeout);
void FD_CLR(int fd, fd_set *set);
int FD_ISSET(int fd, fd_set *set);
void FD_SET(int fd, fd_set *set);
void FD_ZERO(fd_set *set);

select的调用一般要注意几点:
① readfds等是指针结果参数,会被函数修改,所以一般会另外定义一个allread_fdset,保持全部要监听读的句柄,将它的拷贝传递给select函数,返回可读的句柄集合,类型fdset支持赋值运算符=;
② 要注意计算nfds,当新增监听句柄时比较容易修改,当减少监听句柄时较麻烦些,如果要精确修改需要遍历或者采用最大堆等数据结构维护这个句柄集,以方便的找到第二大的句柄,或者干脆在减少监听句柄时不管nfds;
③ timeout如果为NULL表示阻塞等,如果timeout指向的时间为0,表示非阻塞,否则表示select的超时时间;
④ select返回-1表示错误,返回0表示超时时间到没有监听到的事件发生,返回正数表示监听到的所有事件数(包括可读,可写,异常),通常在处理事件时 会利用这个返回值来提高效率,避免不必要的事件触发检查。(比如总共只有一个事件,已经在可读集合中处理了一个事件,则可写和异常就没必要再去遍历句柄集 判断是否发生事件了);
⑤ Linux的实现中select返回时会将timeout修改为剩余时间,所以重复使用timeout需要注意。

select的缺点在于:
① 由于描述符集合set的限制,每个set最多只能监听FD_SETSIZE(在Linux上是1024)个句柄(不同机器可能不一样);
② 返回的可读集合是个fdset类型,需要对所有的监听读句柄一一进行FD_ISSET的测试来判断是否可读;
③ nfds的存在就是为了解决select的效率问题(select遍历nfds个文件描述符,判断每个描述符是否是自己关心的,对关心的描述符判断是否发生事件)。但是解决不彻底,比如如果只监听0和1000两个句柄,select需要遍历1001个句柄来检查事件。


3. epoll
int epoll_create(int size);
int epoll_ctl(int epfd, int op, int fd, struct epoll_event *event);
int epoll_wait(int epfd, struct epoll_event * events, int maxevents, int timeout);

epoll 解决了select和poll的几个性能上的缺陷:①不限制监听的描述符个数(poll也是),只受进程打开描述符总数的限制;②监听性能不随着监听描述 符数的增加而增加,是O(1)的,不再是轮询描述符来探测事件,而是由描述符主动上报事件;③使用共享内存的方式,不在用户和内核之间反复传递监听的描述 符信息;④返回参数中就是触发事件的列表,不用再遍历输入事件表查询各个事件是否被触发。
epoll显著提高性能的前提是:监听大量描述符,并且每次触发事件的描述符文件非常少。
epoll的另外区别是:①epoll创建了描述符,记得close;②支持水平触发和边沿触发。
 

w

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <errno.h>
int main(int argc, char *argv[])
{int ret = mkfifo("myfifo",0666);    if(-1 == ret){//如果是管道文件已存在错误,让程序继续运行if(EEXIST== errno){}else {perror("mkfifo");exit(1);}}//open 会阻塞,等到另一端读段打开,解除阻塞int fd = open("myfifo",O_WRONLY);if(-1 == fd){perror("open");exit(1);}while(1){char buf[256]="hello,fifo,test";write(fd,buf,strlen(buf));sleep(3);}close(fd);return 0;
}

r

  int ret = mkfifo("myfifo",0666);    if(-1 == ret){//如果是管道文件已存在错误,让程序继续运行if(EEXIST== errno){}else {perror("mkfifo");exit(1);}}int fd = open("myfifo",O_RDONLY);if(-1 == fd){perror("open");exit(1);}//1 create set fd_set rd_set,tmp_set;//2 add fd FD_ZERO(&rd_set);FD_ZERO(&tmp_set);FD_SET(fd,&tmp_set);FD_SET(0,&tmp_set);while(1){//4 clean flagrd_set = tmp_set;//3 wait event select(fd+1,&rd_set,NULL,NULL,NULL);char buf[256]={0};if(FD_ISSET(fd,&rd_set)){read(fd,buf,sizeof(buf));printf("fifo %s\n",buf);}if(FD_ISSET(0,&rd_set)){bzero(buf,sizeof(buf));fgets(buf,sizeof(buf),stdin);printf("terminal:%s\n",buf);}}close(fd);

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

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

相关文章

MySQL-ubuntu环境下安装配置mysql

文章目录 什么是数据库&#xff1f;一、ubuntu环境下安装mysql二、配置mysql配置文件1.先登上root账号2.配置文件的修改show engines \G; mysql和mysqld数据库的基础操作登录mysql创建数据库显示当前数据库使用数据库创建表插入students表数据打印students表数据select * from …

AcWing 671. DDD

给定一个整数&#xff0c;请根据下表确定并输出其对应的城市名称&#xff1a; 如果输入数字不在上表中&#xff0c;则输出 DDD nao cadastrado。 输入格式 共一行&#xff0c;包含一个整数。 输出格式 输出对应城市名称&#xff0c;如果没有对应城市名称&#xff0c;则输出…

postman macOS版安装包

链接: https://pan.baidu.com/s/1Y7j4mxB1Otmf3Ku41e7v7w?pwdfy99 提取码: fy99 安装后的效果

闲置服务器废物利用_离线下载_私人影院_个人博客_私人云笔记_文件服务器

背景 家里有台旧windows笔记本&#xff0c;PentiumB940 2.00GHz的cpu 4G内存&#xff0c;512G硬盘 放在家里吃灰很久,最近几个月折腾折腾&#xff0c;装了linux操作系统&#xff0c;换了一个2T的硬盘 这里记录下折腾的过程,有需要的可以参考 开通公网IP 打电话给运营商一般都可…

throw 和throws的区别详解

1. 用法上的区别 throw&#xff1a; 作用&#xff1a;throw是一个关键字&#xff0c;用于在方法体内部抛出一个具体的异常对象。当程序执行到throw语句时&#xff0c;会立即停止当前方法的执行&#xff0c;并将控制权交给该方法的调用者&#xff0c;同时传递异常对象。使用位置…

PyTorch DataLoader 学习

1. DataLoader的核心概念 DataLoader是PyTorch中一个重要的类&#xff0c;用于将数据集&#xff08;dataset&#xff09;和数据加载器&#xff08;sampler&#xff09;结合起来&#xff0c;以实现批量数据加载和处理。它可以高效地处理数据加载、多线程加载、批处理和数据增强…

udp协议模拟远程输入指令控制xshell

不了解udp协议的可以先看一下udp协议下的socket函数_udp socket函数-CSDN博客 我之前还写过模拟实现xshell的模拟实现简单的shell-CSDN博客 如今我们要模拟的是让别人连网络连到我们主机&#xff0c;他可以执行命令&#xff1a; 1.接口 我们之前是用execl系列的函数来实现的…

第三方登录、任意用户登录漏洞总结

目录 1. 第三方昵称为XSS名称 2. 分享接口存在xss漏洞 3. 退出第三方账号仍可以登入 4. 第三方登录绑定漏洞利用(账号接管) 5. 泄漏token接口,任意账号登录 6. jwt未验参/弱密钥 7. cookie可伪造 8. 凭证过早返回 9. 逻辑漏洞导致的任意用户登录 9.1 登录完全依赖数…

IEEE(常用)参考文献引用格式详解 | LaTeX参考文献规范(IEEE Trans、Conf、Arxiv)

IEEE参考文献引用格式注意事项 期刊已正式出版&#xff08;有期卷号&#xff09;录用后在线访问即Early access&#xff08;无期卷号&#xff09; Arxiv论文会议论文IEEE缩写进阶其他 IEEE论文投稿前的参考文献格式检查&#xff01;&#xff08;如果一些细节你采用别的形式&…

香橙派AIpro:体验强劲算力,运行ROS系统

文章目录 前言一、香橙派AIpro开箱及功能介绍1.1香橙派AIpro开箱1.2香橙派AIpro功能介绍 二、香橙派AIpro资料下载及环境搭建2.1资料下载2.2环境搭建2.3使用串口启动进入开发板2.4使用HDMI线接入屏幕启动 三、部署ROS系统四、香橙派AIpro的使用和体验感受 前言 本篇文章将带体…

映射器代理工厂

我们在使用Mybatis时&#xff0c;只需要写Mapper和Dao接口就行&#xff0c;使用的时候只需要调用Dao中的方法就能完成数据的增删改查。那么Dao中的方法是谁实现的呢&#xff1f;难道Mybatis自动帮我们写了一个Dao的实现类吗&#xff1f;非也&#xff01;而是使用了映射器代理工…

在 SwiftUI 中实战使用 MapKit API

文章目录 前言新 MapKit API 的引入控制初始地图位置相机位置的双向绑定总结 前言 SwiftUI 与 MapKit 的集成在今年发生了重大变化。在之前的 SwiftUI 版本中&#xff0c;我们将 MKMapView 的基本功能封装到名为 Map 的 SwiftUI 视图中。幸运的是&#xff0c;事情发生了变化&a…

ontape备份跨服务器还原的样例

1. 查看实例备份参数文件 [gbasedbtiZ2ze5s78e4tanwe5q2znxZ ~]$ onstat -g dis Your evaluation license will expire on 2025-05-26 00:00:00 On-Line -- Up 00:00:15 -- 266536 Kbytes There are 1 servers found Server : node1 Server Number : 1 Server Type :…

虚拟环境操作

1、对虚拟环境的操作 查看虚拟环境列表 conda env list 创建虚拟环境 conda create -n 虚拟环境名称 python3.x 激活虚拟环境 conda activate 虚拟环境名称 退出虚拟环境 conda deactivate 删除虚拟环境 conda remove -n 虚拟环境名称 all 2、对虚拟环境下的包的操作…

力扣题解(分割回文串II)

132. 分割回文串 II 给你一个字符串 s&#xff0c;请你将 s 分割成一些子串&#xff0c;使每个子串都是 回文串 。 返回符合要求的 最少分割次数 思路&#xff1a; 规定dp[i]是以i位置为最后一个元素&#xff0c;&#xff08;0-i&#xff09;的最少分割次数&#xff0c;此…

硅谷并购中的牙刷测试

注&#xff1a;机翻&#xff0c;未校对。 In Silicon Valley, Mergers Must Meet the Toothbrush Test By David Gelles August 17, 2014 9:22 pm Credit Liz Grauman/The New York Times MOUNTAIN VIEW, Calif. — When deciding whether Google should spend millions or …

DP讨论——简单工厂模式

学而时习之&#xff0c;温故而知新。 敌人出招&#xff08;使用场景&#xff09; 不同的业务场景下要创建不同的对象&#xff0c;但是这些对象又有共同的特点。如何复用代码呢&#xff1f;你会想到&#xff0c;这些对象可以抽象出一个基类/抽象类就行了&#xff0c;那么随着业…

docker安装nginx并配置https

参考 docker安装nginx并配置https-腾讯云开发者社区-腾讯云 (tencent.com) 证书的生成 参见&#xff1a;SpringBoot项目配置HTTPS接口的安全访问&#xff08;openssl配置&#xff09;_配置接口访问-CSDN博客 步骤 1: 拉取Nginx镜像 docker pull nginx 好使的镜像如下&#x…

【AI】目标检测算法【R-CNN:Regions with CNN features】

1. 常用目标检测算法介绍 目标检测是计算机视觉领域的一个重要分支&#xff0c;它旨在识别并定位图像中的各种对象。以下是一些流行的目标检测算法&#xff1a; 1.1 二阶段目标检测算法 R-CNN (Regions with CNN features): 通过选择性搜索算法选取候选区域&#xff0c;然后…

vue3-vite-pinia模板

模板说明 下载 git clone https://github.com/AIxiaoHanBao/vue-template.gitmodule参数 node版本 16 UI组件库 element-plus 持久化 pinia 网络请求 axios 路由 vue-router 使用说明 权限管理目录access资源目录assets组件目录components页面目录pages网络请求目录re…